409 lines
14 KiB
C++
409 lines
14 KiB
C++
// Filename: characterJoint.cxx
|
|
// Created by: drose (23Feb99)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "characterJoint.h"
|
|
#include "config_char.h"
|
|
#include "jointVertexTransform.h"
|
|
|
|
#include "datagram.h"
|
|
#include "datagramIterator.h"
|
|
#include "bamReader.h"
|
|
#include "bamWriter.h"
|
|
|
|
TypeHandle CharacterJoint::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::Default Constructor
|
|
// Access: Protected
|
|
// Description: For internal use only.
|
|
////////////////////////////////////////////////////////////////////
|
|
CharacterJoint::
|
|
CharacterJoint() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::Copy Constructor
|
|
// Access: Protected
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CharacterJoint::
|
|
CharacterJoint(const CharacterJoint ©) :
|
|
MovingPartMatrix(copy),
|
|
_net_transform(copy._net_transform),
|
|
_initial_net_transform_inverse(copy._initial_net_transform_inverse)
|
|
{
|
|
// We don't copy the sets of transform nodes.
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CharacterJoint::
|
|
CharacterJoint(PartGroup *parent, const string &name,
|
|
const LMatrix4f &initial_value)
|
|
: MovingPartMatrix(parent, name, initial_value)
|
|
{
|
|
Thread *current_thread = Thread::get_current_thread();
|
|
|
|
// Now that we've constructed and we're in the tree, let's call
|
|
// update_internals() to get our _net_transform set properly.
|
|
update_internals(parent, true, false, current_thread);
|
|
|
|
// And then compute its inverse. This is needed for
|
|
// ComputedVertices, during animation.
|
|
_initial_net_transform_inverse = invert(_net_transform);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CharacterJoint::
|
|
~CharacterJoint() {
|
|
nassertv(_vertex_transforms.empty());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::make_copy
|
|
// Access: Public, Virtual
|
|
// Description: Allocates and returns a new copy of the node.
|
|
// Children are not copied, but see copy_subgraph().
|
|
////////////////////////////////////////////////////////////////////
|
|
PartGroup *CharacterJoint::
|
|
make_copy() const {
|
|
return new CharacterJoint(*this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::update_internals
|
|
// Access: Public, Virtual
|
|
// Description: This is called by do_update() whenever the part or
|
|
// some ancestor has changed values. It is a hook for
|
|
// derived classes to update whatever cache they may
|
|
// have that depends on these.
|
|
//
|
|
// The return value is true if the part has changed as a
|
|
// result of the update, or false otherwise.
|
|
//
|
|
// In the case of a CharacterJoint, of course, it means
|
|
// to recompute the joint angles and associated
|
|
// transforms for this particular joint.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CharacterJoint::
|
|
update_internals(PartGroup *parent, bool self_changed, bool parent_changed,
|
|
Thread *current_thread) {
|
|
|
|
nassertr(parent != (PartGroup *)NULL, false);
|
|
|
|
bool net_changed = false;
|
|
if (parent->is_of_type(CharacterJoint::get_class_type())) {
|
|
// The joint is not a toplevel joint; its parent therefore affects
|
|
// its net transform.
|
|
if (parent_changed || self_changed) {
|
|
CharacterJoint *parent_joint = DCAST(CharacterJoint, parent);
|
|
|
|
_net_transform = _value * parent_joint->_net_transform;
|
|
net_changed = true;
|
|
}
|
|
|
|
} else {
|
|
// The joint *is* a toplevel joint, and the only thing that
|
|
// affects its net transform is the joint itself.
|
|
if (self_changed) {
|
|
_net_transform = _value;
|
|
net_changed = true;
|
|
}
|
|
}
|
|
|
|
if (net_changed) {
|
|
if (!_net_transform_nodes.empty()) {
|
|
CPT(TransformState) t = TransformState::make_mat(_net_transform);
|
|
|
|
NodeList::iterator ai;
|
|
ai = _net_transform_nodes.begin();
|
|
while (ai != _net_transform_nodes.end()) {
|
|
PandaNode *node = *ai;
|
|
node->set_transform(t, current_thread);
|
|
++ai;
|
|
}
|
|
}
|
|
|
|
// Also tell our related JointVertexTransforms that they now need
|
|
// to recompute themselves.
|
|
VertexTransforms::iterator vti;
|
|
for (vti = _vertex_transforms.begin(); vti != _vertex_transforms.end(); ++vti) {
|
|
(*vti)->_matrix_stale = true;
|
|
(*vti)->mark_modified(current_thread);
|
|
}
|
|
}
|
|
|
|
if (self_changed && !_local_transform_nodes.empty()) {
|
|
CPT(TransformState) t = TransformState::make_mat(_value);
|
|
|
|
NodeList::iterator ai;
|
|
ai = _local_transform_nodes.begin();
|
|
while (ai != _local_transform_nodes.end()) {
|
|
PandaNode *node = *ai;
|
|
node->set_transform(t, current_thread);
|
|
++ai;
|
|
}
|
|
}
|
|
|
|
return self_changed || net_changed;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::add_net_transform
|
|
// Access: Published
|
|
// Description: Adds the indicated node to the list of nodes that will
|
|
// be updated each frame with the joint's net transform
|
|
// from the root. Returns true if the node is
|
|
// successfully added, false if it had already been
|
|
// added.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CharacterJoint::
|
|
add_net_transform(PandaNode *node) {
|
|
return _net_transform_nodes.insert(node).second;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::remove_net_transform
|
|
// Access: Published
|
|
// Description: Removes the indicated node from the list of nodes that
|
|
// will be updated each frame with the joint's net
|
|
// transform from the root. Returns true if the node is
|
|
// successfully removed, false if it was not on the
|
|
// list.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CharacterJoint::
|
|
remove_net_transform(PandaNode *node) {
|
|
return (_net_transform_nodes.erase(node) > 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::has_net_transform
|
|
// Access: Published
|
|
// Description: Returns true if the node is on the list of nodes that
|
|
// will be updated each frame with the joint's net
|
|
// transform from the root, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CharacterJoint::
|
|
has_net_transform(PandaNode *node) const {
|
|
return (_net_transform_nodes.count(node) > 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::clear_net_transforms
|
|
// Access: Published
|
|
// Description: Removes all nodes from the list of nodes that will be
|
|
// updated each frame with the joint's net transform
|
|
// from the root.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CharacterJoint::
|
|
clear_net_transforms() {
|
|
_net_transform_nodes.clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::add_local_transform
|
|
// Access: Published
|
|
// Description: Adds the indicated node to the list of nodes that will
|
|
// be updated each frame with the joint's local
|
|
// transform from its parent. Returns true if the node
|
|
// is successfully added, false if it had already been
|
|
// added.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CharacterJoint::
|
|
add_local_transform(PandaNode *node) {
|
|
return _local_transform_nodes.insert(node).second;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::remove_local_transform
|
|
// Access: Published
|
|
// Description: Removes the indicated node from the list of nodes that
|
|
// will be updated each frame with the joint's local
|
|
// transform from its parent. Returns true if the node
|
|
// is successfully removed, false if it was not on the
|
|
// list.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CharacterJoint::
|
|
remove_local_transform(PandaNode *node) {
|
|
return (_local_transform_nodes.erase(node) > 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::has_local_transform
|
|
// Access: Published
|
|
// Description: Returns true if the node is on the list of nodes that
|
|
// will be updated each frame with the joint's local
|
|
// transform from its parent, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CharacterJoint::
|
|
has_local_transform(PandaNode *node) const {
|
|
return (_local_transform_nodes.count(node) > 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::clear_local_transforms
|
|
// Access: Published
|
|
// Description: Removes all nodes from the list of nodes that will be
|
|
// updated each frame with the joint's local transform
|
|
// from its parent.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CharacterJoint::
|
|
clear_local_transforms() {
|
|
_local_transform_nodes.clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::get_transform
|
|
// Access: Published
|
|
// Description: Copies the joint's current transform into the
|
|
// indicated matrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CharacterJoint::
|
|
get_transform(LMatrix4f &transform) const {
|
|
transform = _value;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::get_net_transform
|
|
// Access: Published
|
|
// Description: Copies the joint's current net transform (composed
|
|
// from the root of the character joint hierarchy) into
|
|
// the indicated matrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CharacterJoint::
|
|
get_net_transform(LMatrix4f &transform) const {
|
|
transform = _net_transform;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::write_datagram
|
|
// Access: Public
|
|
// Description: Function to write the important information in
|
|
// the particular object to a Datagram
|
|
////////////////////////////////////////////////////////////////////
|
|
void CharacterJoint::
|
|
write_datagram(BamWriter *manager, Datagram &me)
|
|
{
|
|
NodeList::iterator ni;
|
|
MovingPartMatrix::write_datagram(manager, me);
|
|
|
|
me.add_uint16(_net_transform_nodes.size());
|
|
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++) {
|
|
manager->write_pointer(me, (*ni));
|
|
}
|
|
|
|
_initial_net_transform_inverse.write_datagram(me);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::fillin
|
|
// Access: Protected
|
|
// Description: Function that reads out of the datagram (or asks
|
|
// manager to read) all of the data that is needed to
|
|
// re-create this object and stores it in the appropiate
|
|
// place
|
|
////////////////////////////////////////////////////////////////////
|
|
void CharacterJoint::
|
|
fillin(DatagramIterator &scan, BamReader *manager) {
|
|
int i;
|
|
MovingPartMatrix::fillin(scan, manager);
|
|
|
|
_num_net_nodes = scan.get_uint16();
|
|
for(i = 0; i < _num_net_nodes; i++) {
|
|
manager->read_pointer(scan);
|
|
}
|
|
|
|
_num_local_nodes = scan.get_uint16();
|
|
for(i = 0; i < _num_local_nodes; i++) {
|
|
manager->read_pointer(scan);
|
|
}
|
|
|
|
_initial_net_transform_inverse.read_datagram(scan);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::complete_pointers
|
|
// Access: Public
|
|
// Description: Takes in a vector of pointes 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)
|
|
{
|
|
int pi = MovingPartMatrix::complete_pointers(p_list, manager);
|
|
|
|
int i;
|
|
for (i = 0; i < _num_net_nodes; i++) {
|
|
add_net_transform(DCAST(PandaNode, p_list[pi++]));
|
|
}
|
|
|
|
for (i = 0; i < _num_local_nodes; i++) {
|
|
add_local_transform(DCAST(PandaNode, p_list[pi++]));
|
|
}
|
|
|
|
return pi;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::make_CharacterJoint
|
|
// Access: Protected
|
|
// Description: Factory method to generate a CharacterJoint object
|
|
////////////////////////////////////////////////////////////////////
|
|
TypedWritable* CharacterJoint::
|
|
make_CharacterJoint(const FactoryParams ¶ms)
|
|
{
|
|
CharacterJoint *me = new CharacterJoint;
|
|
DatagramIterator scan;
|
|
BamReader *manager;
|
|
|
|
parse_params(params, scan, manager);
|
|
me->fillin(scan, manager);
|
|
return me;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CharacterJoint::register_with_factory
|
|
// Access: Public, Static
|
|
// Description: Factory method to generate a CharacterJoint object
|
|
////////////////////////////////////////////////////////////////////
|
|
void CharacterJoint::
|
|
register_with_read_factory()
|
|
{
|
|
BamReader::get_factory()->register_factory(get_class_type(), make_CharacterJoint);
|
|
}
|
|
|
|
|