mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
support common transforming of shared PartBundles
This commit is contained in:
parent
1b2a1e605e
commit
7c9997118c
@ -26,6 +26,7 @@
|
||||
movingPartBase.I movingPartBase.h \
|
||||
movingPartMatrix.I movingPartMatrix.h movingPartScalar.I \
|
||||
movingPartScalar.h partBundle.I partBundle.N partBundle.h \
|
||||
partBundleHandle.I partBundleHandle.h \
|
||||
partBundleNode.I partBundleNode.h \
|
||||
partGroup.I partGroup.h \
|
||||
partSubset.I partSubset.h \
|
||||
@ -45,6 +46,7 @@
|
||||
animControlCollection.cxx animGroup.cxx auto_bind.cxx \
|
||||
config_chan.cxx movingPartBase.cxx movingPartMatrix.cxx \
|
||||
movingPartScalar.cxx partBundle.cxx \
|
||||
partBundleHandle.cxx \
|
||||
partBundleNode.cxx \
|
||||
partGroup.cxx \
|
||||
partSubset.cxx \
|
||||
@ -66,6 +68,7 @@
|
||||
movingPart.I movingPart.h movingPartBase.I \
|
||||
movingPartBase.h movingPartMatrix.I movingPartMatrix.h \
|
||||
movingPartScalar.I movingPartScalar.h partBundle.I partBundle.h \
|
||||
partBundleHandle.I partBundleHandle.h \
|
||||
partBundleNode.I partBundleNode.h \
|
||||
partGroup.I partGroup.h \
|
||||
partSubset.I partSubset.h \
|
||||
|
@ -124,6 +124,46 @@ set_anim_blend_flag(bool anim_blend_flag) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::apply_transform
|
||||
// Access: Published
|
||||
// Description: Returns a PartBundle that is a duplicate of this one,
|
||||
// but with the indicated transform applied. If this is
|
||||
// called multiple times with the same TransformState
|
||||
// pointer, it returns the same PartBundle each time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(PartBundle) PartBundle::
|
||||
apply_transform(const TransformState *transform) {
|
||||
if (transform->is_identity()) {
|
||||
// Trivial no-op.
|
||||
return this;
|
||||
}
|
||||
|
||||
AppliedTransforms::iterator ati = _applied_transforms.find(transform);
|
||||
if (ati != _applied_transforms.end()) {
|
||||
if ((*ati).first.is_valid_pointer() &&
|
||||
(*ati).second.is_valid_pointer()) {
|
||||
// Here's our cached result.
|
||||
return (*ati).second.p();
|
||||
}
|
||||
}
|
||||
|
||||
PT(PartBundle) new_bundle = DCAST(PartBundle, copy_subgraph());
|
||||
new_bundle->xform(transform->get_mat());
|
||||
|
||||
if (ati != _applied_transforms.end()) {
|
||||
// A stale pointer to a deleted result. Update it.
|
||||
(*ati).first.refresh();
|
||||
(*ati).second = new_bundle;
|
||||
} else {
|
||||
// No such result yet. Store it.
|
||||
bool inserted = _applied_transforms.insert(AppliedTransforms::value_type(transform, new_bundle)).second;
|
||||
nassertr(inserted, new_bundle);
|
||||
}
|
||||
|
||||
return new_bundle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::clear_control_effects
|
||||
// Access: Published
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "cycleDataWriter.h"
|
||||
#include "luse.h"
|
||||
#include "pvector.h"
|
||||
#include "transformState.h"
|
||||
#include "weakPointerTo.h"
|
||||
|
||||
class AnimBundle;
|
||||
class PartBundleNode;
|
||||
@ -106,6 +108,7 @@ PUBLISHED:
|
||||
INLINE void set_root_xform(const LMatrix4f &root_xform);
|
||||
INLINE void xform(const LMatrix4f &mat);
|
||||
INLINE const LMatrix4f &get_root_xform() const;
|
||||
PT(PartBundle) apply_transform(const TransformState *transform);
|
||||
|
||||
INLINE int get_num_nodes() const;
|
||||
INLINE PartBundleNode *get_node(int n) const;
|
||||
@ -149,6 +152,9 @@ private:
|
||||
typedef pvector<PartBundleNode *> Nodes;
|
||||
Nodes _nodes;
|
||||
|
||||
typedef pmap<WCPT(TransformState), WPT(PartBundle) > AppliedTransforms;
|
||||
AppliedTransforms _applied_transforms;
|
||||
|
||||
// This is the data that must be cycled between pipeline stages.
|
||||
class CData : public CycleData {
|
||||
public:
|
||||
|
60
panda/src/chan/partBundleHandle.I
Normal file
60
panda/src/chan/partBundleHandle.I
Normal file
@ -0,0 +1,60 @@
|
||||
// Filename: partBundleHandle.I
|
||||
// Created by: drose (01Oct07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: PartBundleHandle::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundleHandle::
|
||||
PartBundleHandle(PartBundle *bundle) :
|
||||
_bundle(bundle)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleHandle::Destructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundleHandle::
|
||||
~PartBundleHandle() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleHandle::get_bundle
|
||||
// Access: Published
|
||||
// Description: Returns the actual PartBundle embedded within the
|
||||
// handle.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundle *PartBundleHandle::
|
||||
get_bundle() {
|
||||
return _bundle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleHandle::set_bundle
|
||||
// Access: Published
|
||||
// Description: Changes the actual PartBundle embedded within the
|
||||
// handle.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PartBundleHandle::
|
||||
set_bundle(PartBundle *bundle) {
|
||||
_bundle = bundle;
|
||||
}
|
19
panda/src/chan/partBundleHandle.cxx
Normal file
19
panda/src/chan/partBundleHandle.cxx
Normal file
@ -0,0 +1,19 @@
|
||||
// Filename: partBundleHandle.cxx
|
||||
// Created by: drose (01Oct07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "partBundleHandle.h"
|
57
panda/src/chan/partBundleHandle.h
Normal file
57
panda/src/chan/partBundleHandle.h
Normal file
@ -0,0 +1,57 @@
|
||||
// Filename: partBundleHandle.h
|
||||
// Created by: drose (01Oct07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PARTBUNDLEHANDLE_H
|
||||
#define PARTBUNDLEHANDLE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "partBundle.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PartBundleHandle
|
||||
// Description : This is a trivial class returned by
|
||||
// PartBundleNode::get_bundle(). Its purpose is to hold
|
||||
// the actual PartBundle pointer contained within the
|
||||
// PartBundleNode, so that scene graph flatten
|
||||
// operations can safely combine or duplicate
|
||||
// PartBundles as necessary without affecting high-level
|
||||
// bundle operations.
|
||||
//
|
||||
// The high-level Actor class defined in
|
||||
// direct/src/actor, for instance, will store a list of
|
||||
// PartBundleHandles instead of on actual PartBundles,
|
||||
// so that it will be immune to changes from these
|
||||
// flatten operations.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_CHAN PartBundleHandle : public ReferenceCount {
|
||||
PUBLISHED:
|
||||
INLINE PartBundleHandle(PartBundle *bundle);
|
||||
INLINE ~PartBundleHandle();
|
||||
|
||||
INLINE PartBundle *get_bundle();
|
||||
INLINE void set_bundle(PartBundle *bundle);
|
||||
|
||||
private:
|
||||
PT(PartBundle) _bundle;
|
||||
};
|
||||
|
||||
#include "partBundleHandle.I"
|
||||
|
||||
#endif
|
@ -73,6 +73,20 @@ get_num_bundles() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundle *PartBundleNode::
|
||||
get_bundle(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_bundles.size(), NULL);
|
||||
return _bundles[n]->get_bundle();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleNode::get_bundle_handle
|
||||
// Access: Public
|
||||
// Description: Returns the PartBundleHandle that wraps around the
|
||||
// actual nth PartBundle. While the PartBundle pointer
|
||||
// might later change due to a future flatten operation,
|
||||
// the PartBundleHandle will not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundleHandle *PartBundleNode::
|
||||
get_bundle_handle(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_bundles.size(), NULL);
|
||||
return _bundles[n];
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "datagramIterator.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "sceneGraphReducer.h"
|
||||
|
||||
TypeHandle PartBundleNode::_type_handle;
|
||||
|
||||
@ -33,29 +34,34 @@ PartBundleNode::
|
||||
~PartBundleNode() {
|
||||
Bundles::iterator bi;
|
||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||
(*bi)->remove_node(this);
|
||||
(*bi)->get_bundle()->remove_node(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleNode::safe_to_transform
|
||||
// Function: PartBundleNode::apply_attribs_to_vertices
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if it is generally safe to transform
|
||||
// this particular kind of PandaNode by calling the
|
||||
// xform() method, false otherwise.
|
||||
// Description: Applies whatever attributes are specified in the
|
||||
// AccumulatedAttribs object (and by the attrib_types
|
||||
// bitmask) to the vertices on this node, if
|
||||
// appropriate. If this node uses geom arrays like a
|
||||
// GeomNode, the supplied GeomTransformer may be used to
|
||||
// unify shared arrays across multiple different nodes.
|
||||
//
|
||||
// This is a generalization of xform().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PartBundleNode::
|
||||
safe_to_transform() const {
|
||||
// If any of our bundles appear on multiple nodes, we can't
|
||||
// transform any of them without transforming all of them at once.
|
||||
Bundles::const_iterator bi;
|
||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||
if ((*bi)->get_num_nodes() > 1) {
|
||||
return false;
|
||||
void PartBundleNode::
|
||||
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
||||
GeomTransformer &transformer) {
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
Bundles::iterator bi;
|
||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||
PT(PartBundleHandle) handle = (*bi);
|
||||
PartBundle *bundle = handle->get_bundle();
|
||||
PT(PartBundle) new_bundle = bundle->apply_transform(attribs._transform);
|
||||
update_bundle(handle, new_bundle);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -67,6 +73,10 @@ safe_to_transform() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundleNode::
|
||||
xform(const LMatrix4f &mat) {
|
||||
// With plain xform(), we can't attempt to share bundles across
|
||||
// different nodes. Better to use apply_attribs_to_vertices(),
|
||||
// instead.
|
||||
|
||||
if (mat.almost_equal(LMatrix4f::ident_mat())) {
|
||||
// Don't bother.
|
||||
return;
|
||||
@ -74,7 +84,14 @@ xform(const LMatrix4f &mat) {
|
||||
|
||||
Bundles::iterator bi;
|
||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||
(*bi)->xform(mat);
|
||||
PT(PartBundleHandle) handle = (*bi);
|
||||
PartBundle *bundle = handle->get_bundle();
|
||||
if (bundle->get_num_nodes() > 1) {
|
||||
PT(PartBundle) new_bundle = DCAST(PartBundle, bundle->copy_subgraph());
|
||||
update_bundle(handle, new_bundle);
|
||||
bundle = new_bundle;
|
||||
}
|
||||
bundle->xform(mat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,8 +102,25 @@ xform(const LMatrix4f &mat) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundleNode::
|
||||
add_bundle(PartBundle *bundle) {
|
||||
_bundles.push_back(bundle);
|
||||
bundle->add_node(this);
|
||||
PT(PartBundleHandle) handle = new PartBundleHandle(bundle);
|
||||
add_bundle_handle(handle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleNode::add_bundle_handle
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundleNode::
|
||||
add_bundle_handle(PartBundleHandle *handle) {
|
||||
Bundles::iterator bi = find(_bundles.begin(), _bundles.end(), handle);
|
||||
if (bi != _bundles.end()) {
|
||||
// This handle is already within the node.
|
||||
return;
|
||||
}
|
||||
|
||||
_bundles.push_back(handle);
|
||||
handle->get_bundle()->add_node(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -97,16 +131,34 @@ add_bundle(PartBundle *bundle) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundleNode::
|
||||
steal_bundles(PartBundleNode *other) {
|
||||
if (other == this) {
|
||||
return;
|
||||
}
|
||||
|
||||
Bundles::iterator bi;
|
||||
for (bi = other->_bundles.begin(); bi != other->_bundles.end(); ++bi) {
|
||||
PartBundle *bundle = (*bi);
|
||||
_bundles.push_back(bundle);
|
||||
bundle->remove_node(other);
|
||||
bundle->add_node(this);
|
||||
PartBundleHandle *handle = (*bi);
|
||||
handle->get_bundle()->remove_node(other);
|
||||
add_bundle_handle(handle);
|
||||
}
|
||||
other->_bundles.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleNode::update_bundle
|
||||
// Access: Protected, Virtual
|
||||
// Description: Replaces the contents of the indicated
|
||||
// PartBundleHandle (presumably stored within this node)
|
||||
// with new_bundle.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundleNode::
|
||||
update_bundle(PartBundleHandle *old_bundle_handle, PartBundle *new_bundle) {
|
||||
PartBundle *old_bundle = old_bundle_handle->get_bundle();
|
||||
old_bundle->remove_node(this);
|
||||
old_bundle_handle->set_bundle(new_bundle);
|
||||
new_bundle->add_node(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundleNode::write_datagram
|
||||
// Access: Public, Virtual
|
||||
@ -120,7 +172,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
dg.add_uint16(_bundles.size());
|
||||
Bundles::iterator bi;
|
||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||
manager->write_pointer(dg, (*bi));
|
||||
manager->write_pointer(dg, (*bi)->get_bundle());
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,8 +189,9 @@ complete_pointers(TypedWritable **p_list, BamReader* manager) {
|
||||
|
||||
Bundles::iterator bi;
|
||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||
(*bi) = DCAST(PartBundle, p_list[pi++]);
|
||||
(*bi)->add_node(this);
|
||||
PT(PartBundle) bundle = DCAST(PartBundle, p_list[pi++]);
|
||||
bundle->add_node(this);
|
||||
(*bi) = new PartBundleHandle(bundle);
|
||||
}
|
||||
|
||||
return pi;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "partBundle.h"
|
||||
#include "partBundleHandle.h"
|
||||
|
||||
#include "pandaNode.h"
|
||||
#include "dcast.h"
|
||||
@ -43,19 +44,25 @@ protected:
|
||||
|
||||
public:
|
||||
virtual ~PartBundleNode();
|
||||
virtual bool safe_to_transform() const;
|
||||
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
|
||||
int attrib_types,
|
||||
GeomTransformer &transformer);
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE int get_num_bundles() const;
|
||||
INLINE PartBundle *get_bundle(int n) const;
|
||||
INLINE PartBundleHandle *get_bundle_handle(int n) const;
|
||||
|
||||
protected:
|
||||
void add_bundle(PartBundle *bundle);
|
||||
void add_bundle_handle(PartBundleHandle *handle);
|
||||
void steal_bundles(PartBundleNode *other);
|
||||
virtual void update_bundle(PartBundleHandle *old_bundle_handle,
|
||||
PartBundle *new_bundle);
|
||||
|
||||
protected:
|
||||
typedef pvector< PT(PartBundle) > Bundles;
|
||||
typedef pvector< PT(PartBundleHandle) > Bundles;
|
||||
Bundles _bundles;
|
||||
|
||||
public:
|
||||
|
@ -230,6 +230,43 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
|
||||
// pointer, and all geometry within this node will be
|
||||
// updated to reference new_bundle.
|
||||
//
|
||||
// This method is deprecated. Use the newer version of
|
||||
// this method, below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Character::
|
||||
merge_bundles(PartBundle *old_bundle, PartBundle *new_bundle) {
|
||||
if (old_bundle == new_bundle) {
|
||||
// Trivially return.
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the PartBundleHandle of old_bundle.
|
||||
PT(PartBundleHandle) old_bundle_handle;
|
||||
Bundles::const_iterator bi;
|
||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||
if ((*bi)->get_bundle() == old_bundle) {
|
||||
old_bundle_handle = (*bi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
nassertv(!old_bundle_handle.is_null());
|
||||
|
||||
PT(PartBundleHandle) new_bundle_handle = new PartBundleHandle(new_bundle);
|
||||
merge_bundles(old_bundle_handle, new_bundle_handle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Character::merge_bundles
|
||||
// Access: Published
|
||||
// Description: Merges old_bundle_handle->get_bundle() with
|
||||
// new_bundle. old_bundle_handle must be one of the
|
||||
// PartBundleHandle within this node. At the end of
|
||||
// this call, the bundle pointer within the
|
||||
// old_bundle_handle will be replaced with that within
|
||||
// the new_bundle_handle pointer, and all geometry
|
||||
// within this node will be updated to reference
|
||||
// new_bundle.
|
||||
//
|
||||
// Normally, this is called when the two bundles have
|
||||
// the same, or nearly the same, hierarchies. In this
|
||||
// case, new_bundle will simply be assigned over the
|
||||
@ -246,34 +283,9 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
|
||||
// LOD's of the same model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Character::
|
||||
merge_bundles(PartBundle *old_bundle, PartBundle *new_bundle) {
|
||||
// Find the index number of old_bundle.
|
||||
size_t index = 0;
|
||||
while (index < _bundles.size()) {
|
||||
if (_bundles[index] == old_bundle) {
|
||||
break;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
nassertv_always(index < _bundles.size());
|
||||
|
||||
if (old_bundle == new_bundle) {
|
||||
// Trivially return.
|
||||
return;
|
||||
}
|
||||
|
||||
// First, merge the bundles themselves.
|
||||
JointMap joint_map;
|
||||
r_merge_bundles(joint_map, old_bundle, new_bundle);
|
||||
old_bundle->remove_node(this);
|
||||
_bundles[index] = new_bundle;
|
||||
new_bundle->add_node(this);
|
||||
|
||||
// Now convert the geometry to use the new bundle.
|
||||
GeomVertexMap gvmap;
|
||||
GeomJointMap gjmap;
|
||||
GeomSliderMap gsmap;
|
||||
r_update_geom(this, joint_map, gvmap, gjmap, gsmap);
|
||||
merge_bundles(PartBundleHandle *old_bundle_handle,
|
||||
PartBundleHandle *new_bundle_handle) {
|
||||
update_bundle(old_bundle_handle, new_bundle_handle->get_bundle());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -405,28 +417,6 @@ force_update() {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Character::do_update
|
||||
// Access: Private
|
||||
// Description: The actual implementation of update(). Assumes the
|
||||
// appropriate PStatCollector has already been started.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Character::
|
||||
do_update() {
|
||||
// Update all the joints and sliders.
|
||||
if (even_animation) {
|
||||
int num_bundles = get_num_bundles();
|
||||
for (int i = 0; i < num_bundles; ++i) {
|
||||
get_bundle(i)->force_update();
|
||||
}
|
||||
} else {
|
||||
int num_bundles = get_num_bundles();
|
||||
for (int i = 0; i < num_bundles; ++i) {
|
||||
get_bundle(i)->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Character::r_copy_children
|
||||
// Access: Protected, Virtual
|
||||
@ -475,6 +465,56 @@ r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Character::update_bundle
|
||||
// Access: Protected, Virtual
|
||||
// Description: Replaces the contents of the indicated
|
||||
// PartBundleHandle (presumably stored within this node)
|
||||
// with new_bundle.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Character::
|
||||
update_bundle(PartBundleHandle *old_bundle_handle, PartBundle *new_bundle) {
|
||||
if (old_bundle_handle->get_bundle() == new_bundle) {
|
||||
// Trivially return.
|
||||
return;
|
||||
}
|
||||
|
||||
// First, merge the bundles, to ensure we have the same set of
|
||||
// joints in the new bundle.
|
||||
JointMap joint_map;
|
||||
r_merge_bundles(joint_map, old_bundle_handle->get_bundle(), new_bundle);
|
||||
|
||||
PartBundleNode::update_bundle(old_bundle_handle, new_bundle);
|
||||
|
||||
// Now convert the geometry to use the new bundle.
|
||||
GeomVertexMap gvmap;
|
||||
GeomJointMap gjmap;
|
||||
GeomSliderMap gsmap;
|
||||
r_update_geom(this, joint_map, gvmap, gjmap, gsmap);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Character::do_update
|
||||
// Access: Private
|
||||
// Description: The actual implementation of update(). Assumes the
|
||||
// appropriate PStatCollector has already been started.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Character::
|
||||
do_update() {
|
||||
// Update all the joints and sliders.
|
||||
if (even_animation) {
|
||||
int num_bundles = get_num_bundles();
|
||||
for (int i = 0; i < num_bundles; ++i) {
|
||||
get_bundle(i)->force_update();
|
||||
}
|
||||
} else {
|
||||
int num_bundles = get_num_bundles();
|
||||
for (int i = 0; i < num_bundles; ++i) {
|
||||
get_bundle(i)->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Character::fill_joint_map
|
||||
// Access: Private
|
||||
|
@ -65,6 +65,8 @@ public:
|
||||
PUBLISHED:
|
||||
INLINE CharacterJointBundle *get_bundle(int i) const;
|
||||
void merge_bundles(PartBundle *old_bundle, PartBundle *other_bundle);
|
||||
void merge_bundles(PartBundleHandle *old_bundle_handle,
|
||||
PartBundleHandle *other_bundle_handle);
|
||||
|
||||
CharacterJoint *find_joint(const string &name) const;
|
||||
CharacterSlider *find_slider(const string &name) const;
|
||||
@ -76,6 +78,12 @@ PUBLISHED:
|
||||
void update();
|
||||
void force_update();
|
||||
|
||||
protected:
|
||||
virtual void r_copy_children(const PandaNode *from, InstanceMap &inst_map,
|
||||
Thread *current_thread);
|
||||
virtual void update_bundle(PartBundleHandle *old_bundle_handle,
|
||||
PartBundle *new_bundle);
|
||||
|
||||
private:
|
||||
void do_update();
|
||||
|
||||
@ -85,8 +93,6 @@ private:
|
||||
typedef pmap<const VertexTransform *, PT(JointVertexTransform) > GeomJointMap;
|
||||
typedef pmap<const VertexSlider *, PT(CharacterVertexSlider) > GeomSliderMap;
|
||||
|
||||
virtual void r_copy_children(const PandaNode *from, InstanceMap &inst_map,
|
||||
Thread *current_thread);
|
||||
void fill_joint_map(JointMap &joint_map, PartGroup *copy, PartGroup *orig);
|
||||
void r_merge_bundles(Character::JointMap &joint_map,
|
||||
PartGroup *old_group, PartGroup *new_group);
|
||||
|
@ -399,6 +399,24 @@ clear() {
|
||||
reassign((To *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakPointerToBase::refresh
|
||||
// Access: Published
|
||||
// Description: Informs the WeakPointerTo object that its pointer is
|
||||
// no longer deleted. This may be used after a
|
||||
// WeakPointerTo has deleted a deleted pointer, and then
|
||||
// a new pointer has been reallocated. It's equivalent
|
||||
// to simply reassigning the pointer to its new
|
||||
// (i.e. original) value, but has the advantage that it
|
||||
// is const, so can be used for WeakPointers used as
|
||||
// keys in STL maps and sets.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void WeakPointerToBase<T>::
|
||||
refresh() const {
|
||||
((WeakPointerToBase<T> *)this)->reassign((To *)_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakPointerToBase::output
|
||||
// Access: Published
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
|
||||
PUBLISHED:
|
||||
INLINE void clear();
|
||||
INLINE void refresh() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
};
|
||||
|
@ -116,7 +116,9 @@ flatten(PandaNode *root, int combine_siblings_bits) {
|
||||
num_pass_nodes += r_flatten(root, child_node, combine_siblings_bits);
|
||||
}
|
||||
|
||||
if (combine_siblings_bits != 0 && root->get_num_children() >= 2) {
|
||||
if (combine_siblings_bits != 0 &&
|
||||
root->get_num_children() >= 2 &&
|
||||
root->safe_to_combine_children()) {
|
||||
num_pass_nodes += flatten_siblings(root, combine_siblings_bits);
|
||||
}
|
||||
|
||||
@ -397,7 +399,7 @@ r_flatten(PandaNode *grandparent_node, PandaNode *parent_node,
|
||||
|
||||
// Finally, if any of our remaining children are plain PandaNodes
|
||||
// with no children, just remove them.
|
||||
{
|
||||
if (parent_node->safe_to_combine_children()) {
|
||||
for (int i = parent_node->get_num_children() - 1; i >= 0; --i) {
|
||||
PandaNode *child_node = parent_node->get_child(i);
|
||||
if (child_node->is_exact_type(PandaNode::get_class_type()) &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user