mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -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 \
|
movingPartBase.I movingPartBase.h \
|
||||||
movingPartMatrix.I movingPartMatrix.h movingPartScalar.I \
|
movingPartMatrix.I movingPartMatrix.h movingPartScalar.I \
|
||||||
movingPartScalar.h partBundle.I partBundle.N partBundle.h \
|
movingPartScalar.h partBundle.I partBundle.N partBundle.h \
|
||||||
|
partBundleHandle.I partBundleHandle.h \
|
||||||
partBundleNode.I partBundleNode.h \
|
partBundleNode.I partBundleNode.h \
|
||||||
partGroup.I partGroup.h \
|
partGroup.I partGroup.h \
|
||||||
partSubset.I partSubset.h \
|
partSubset.I partSubset.h \
|
||||||
@ -45,6 +46,7 @@
|
|||||||
animControlCollection.cxx animGroup.cxx auto_bind.cxx \
|
animControlCollection.cxx animGroup.cxx auto_bind.cxx \
|
||||||
config_chan.cxx movingPartBase.cxx movingPartMatrix.cxx \
|
config_chan.cxx movingPartBase.cxx movingPartMatrix.cxx \
|
||||||
movingPartScalar.cxx partBundle.cxx \
|
movingPartScalar.cxx partBundle.cxx \
|
||||||
|
partBundleHandle.cxx \
|
||||||
partBundleNode.cxx \
|
partBundleNode.cxx \
|
||||||
partGroup.cxx \
|
partGroup.cxx \
|
||||||
partSubset.cxx \
|
partSubset.cxx \
|
||||||
@ -66,6 +68,7 @@
|
|||||||
movingPart.I movingPart.h movingPartBase.I \
|
movingPart.I movingPart.h movingPartBase.I \
|
||||||
movingPartBase.h movingPartMatrix.I movingPartMatrix.h \
|
movingPartBase.h movingPartMatrix.I movingPartMatrix.h \
|
||||||
movingPartScalar.I movingPartScalar.h partBundle.I partBundle.h \
|
movingPartScalar.I movingPartScalar.h partBundle.I partBundle.h \
|
||||||
|
partBundleHandle.I partBundleHandle.h \
|
||||||
partBundleNode.I partBundleNode.h \
|
partBundleNode.I partBundleNode.h \
|
||||||
partGroup.I partGroup.h \
|
partGroup.I partGroup.h \
|
||||||
partSubset.I partSubset.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
|
// Function: PartBundle::clear_control_effects
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include "cycleDataWriter.h"
|
#include "cycleDataWriter.h"
|
||||||
#include "luse.h"
|
#include "luse.h"
|
||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
|
#include "transformState.h"
|
||||||
|
#include "weakPointerTo.h"
|
||||||
|
|
||||||
class AnimBundle;
|
class AnimBundle;
|
||||||
class PartBundleNode;
|
class PartBundleNode;
|
||||||
@ -106,6 +108,7 @@ PUBLISHED:
|
|||||||
INLINE void set_root_xform(const LMatrix4f &root_xform);
|
INLINE void set_root_xform(const LMatrix4f &root_xform);
|
||||||
INLINE void xform(const LMatrix4f &mat);
|
INLINE void xform(const LMatrix4f &mat);
|
||||||
INLINE const LMatrix4f &get_root_xform() const;
|
INLINE const LMatrix4f &get_root_xform() const;
|
||||||
|
PT(PartBundle) apply_transform(const TransformState *transform);
|
||||||
|
|
||||||
INLINE int get_num_nodes() const;
|
INLINE int get_num_nodes() const;
|
||||||
INLINE PartBundleNode *get_node(int n) const;
|
INLINE PartBundleNode *get_node(int n) const;
|
||||||
@ -149,6 +152,9 @@ private:
|
|||||||
typedef pvector<PartBundleNode *> Nodes;
|
typedef pvector<PartBundleNode *> Nodes;
|
||||||
Nodes _nodes;
|
Nodes _nodes;
|
||||||
|
|
||||||
|
typedef pmap<WCPT(TransformState), WPT(PartBundle) > AppliedTransforms;
|
||||||
|
AppliedTransforms _applied_transforms;
|
||||||
|
|
||||||
// This is the data that must be cycled between pipeline stages.
|
// This is the data that must be cycled between pipeline stages.
|
||||||
class CData : public CycleData {
|
class CData : public CycleData {
|
||||||
public:
|
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::
|
INLINE PartBundle *PartBundleNode::
|
||||||
get_bundle(int n) const {
|
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);
|
nassertr(n >= 0 && n < (int)_bundles.size(), NULL);
|
||||||
return _bundles[n];
|
return _bundles[n];
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "datagramIterator.h"
|
#include "datagramIterator.h"
|
||||||
#include "bamReader.h"
|
#include "bamReader.h"
|
||||||
#include "bamWriter.h"
|
#include "bamWriter.h"
|
||||||
|
#include "sceneGraphReducer.h"
|
||||||
|
|
||||||
TypeHandle PartBundleNode::_type_handle;
|
TypeHandle PartBundleNode::_type_handle;
|
||||||
|
|
||||||
@ -33,29 +34,34 @@ PartBundleNode::
|
|||||||
~PartBundleNode() {
|
~PartBundleNode() {
|
||||||
Bundles::iterator bi;
|
Bundles::iterator bi;
|
||||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++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
|
// Access: Public, Virtual
|
||||||
// Description: Returns true if it is generally safe to transform
|
// Description: Applies whatever attributes are specified in the
|
||||||
// this particular kind of PandaNode by calling the
|
// AccumulatedAttribs object (and by the attrib_types
|
||||||
// xform() method, false otherwise.
|
// 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::
|
void PartBundleNode::
|
||||||
safe_to_transform() const {
|
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
||||||
// If any of our bundles appear on multiple nodes, we can't
|
GeomTransformer &transformer) {
|
||||||
// transform any of them without transforming all of them at once.
|
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||||
Bundles::const_iterator bi;
|
Bundles::iterator bi;
|
||||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||||
if ((*bi)->get_num_nodes() > 1) {
|
PT(PartBundleHandle) handle = (*bi);
|
||||||
return false;
|
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::
|
void PartBundleNode::
|
||||||
xform(const LMatrix4f &mat) {
|
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())) {
|
if (mat.almost_equal(LMatrix4f::ident_mat())) {
|
||||||
// Don't bother.
|
// Don't bother.
|
||||||
return;
|
return;
|
||||||
@ -74,7 +84,14 @@ xform(const LMatrix4f &mat) {
|
|||||||
|
|
||||||
Bundles::iterator bi;
|
Bundles::iterator bi;
|
||||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++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::
|
void PartBundleNode::
|
||||||
add_bundle(PartBundle *bundle) {
|
add_bundle(PartBundle *bundle) {
|
||||||
_bundles.push_back(bundle);
|
PT(PartBundleHandle) handle = new PartBundleHandle(bundle);
|
||||||
bundle->add_node(this);
|
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::
|
void PartBundleNode::
|
||||||
steal_bundles(PartBundleNode *other) {
|
steal_bundles(PartBundleNode *other) {
|
||||||
|
if (other == this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Bundles::iterator bi;
|
Bundles::iterator bi;
|
||||||
for (bi = other->_bundles.begin(); bi != other->_bundles.end(); ++bi) {
|
for (bi = other->_bundles.begin(); bi != other->_bundles.end(); ++bi) {
|
||||||
PartBundle *bundle = (*bi);
|
PartBundleHandle *handle = (*bi);
|
||||||
_bundles.push_back(bundle);
|
handle->get_bundle()->remove_node(other);
|
||||||
bundle->remove_node(other);
|
add_bundle_handle(handle);
|
||||||
bundle->add_node(this);
|
|
||||||
}
|
}
|
||||||
other->_bundles.clear();
|
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
|
// Function: PartBundleNode::write_datagram
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -120,7 +172,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
|||||||
dg.add_uint16(_bundles.size());
|
dg.add_uint16(_bundles.size());
|
||||||
Bundles::iterator bi;
|
Bundles::iterator bi;
|
||||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++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;
|
Bundles::iterator bi;
|
||||||
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
|
||||||
(*bi) = DCAST(PartBundle, p_list[pi++]);
|
PT(PartBundle) bundle = DCAST(PartBundle, p_list[pi++]);
|
||||||
(*bi)->add_node(this);
|
bundle->add_node(this);
|
||||||
|
(*bi) = new PartBundleHandle(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pi;
|
return pi;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
|
|
||||||
#include "partBundle.h"
|
#include "partBundle.h"
|
||||||
|
#include "partBundleHandle.h"
|
||||||
|
|
||||||
#include "pandaNode.h"
|
#include "pandaNode.h"
|
||||||
#include "dcast.h"
|
#include "dcast.h"
|
||||||
@ -43,19 +44,25 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~PartBundleNode();
|
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);
|
virtual void xform(const LMatrix4f &mat);
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE int get_num_bundles() const;
|
INLINE int get_num_bundles() const;
|
||||||
INLINE PartBundle *get_bundle(int n) const;
|
INLINE PartBundle *get_bundle(int n) const;
|
||||||
|
INLINE PartBundleHandle *get_bundle_handle(int n) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void add_bundle(PartBundle *bundle);
|
void add_bundle(PartBundle *bundle);
|
||||||
|
void add_bundle_handle(PartBundleHandle *handle);
|
||||||
void steal_bundles(PartBundleNode *other);
|
void steal_bundles(PartBundleNode *other);
|
||||||
|
virtual void update_bundle(PartBundleHandle *old_bundle_handle,
|
||||||
|
PartBundle *new_bundle);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef pvector< PT(PartBundle) > Bundles;
|
typedef pvector< PT(PartBundleHandle) > Bundles;
|
||||||
Bundles _bundles;
|
Bundles _bundles;
|
||||||
|
|
||||||
public:
|
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
|
// pointer, and all geometry within this node will be
|
||||||
// updated to reference new_bundle.
|
// 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
|
// Normally, this is called when the two bundles have
|
||||||
// the same, or nearly the same, hierarchies. In this
|
// the same, or nearly the same, hierarchies. In this
|
||||||
// case, new_bundle will simply be assigned over the
|
// 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.
|
// LOD's of the same model.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void Character::
|
void Character::
|
||||||
merge_bundles(PartBundle *old_bundle, PartBundle *new_bundle) {
|
merge_bundles(PartBundleHandle *old_bundle_handle,
|
||||||
// Find the index number of old_bundle.
|
PartBundleHandle *new_bundle_handle) {
|
||||||
size_t index = 0;
|
update_bundle(old_bundle_handle, new_bundle_handle->get_bundle());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -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
|
// Function: Character::r_copy_children
|
||||||
// Access: Protected, Virtual
|
// 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
|
// Function: Character::fill_joint_map
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -65,6 +65,8 @@ public:
|
|||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE CharacterJointBundle *get_bundle(int i) const;
|
INLINE CharacterJointBundle *get_bundle(int i) const;
|
||||||
void merge_bundles(PartBundle *old_bundle, PartBundle *other_bundle);
|
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;
|
CharacterJoint *find_joint(const string &name) const;
|
||||||
CharacterSlider *find_slider(const string &name) const;
|
CharacterSlider *find_slider(const string &name) const;
|
||||||
@ -76,6 +78,12 @@ PUBLISHED:
|
|||||||
void update();
|
void update();
|
||||||
void force_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:
|
private:
|
||||||
void do_update();
|
void do_update();
|
||||||
|
|
||||||
@ -85,8 +93,6 @@ private:
|
|||||||
typedef pmap<const VertexTransform *, PT(JointVertexTransform) > GeomJointMap;
|
typedef pmap<const VertexTransform *, PT(JointVertexTransform) > GeomJointMap;
|
||||||
typedef pmap<const VertexSlider *, PT(CharacterVertexSlider) > GeomSliderMap;
|
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 fill_joint_map(JointMap &joint_map, PartGroup *copy, PartGroup *orig);
|
||||||
void r_merge_bundles(Character::JointMap &joint_map,
|
void r_merge_bundles(Character::JointMap &joint_map,
|
||||||
PartGroup *old_group, PartGroup *new_group);
|
PartGroup *old_group, PartGroup *new_group);
|
||||||
|
@ -399,6 +399,24 @@ clear() {
|
|||||||
reassign((To *)NULL);
|
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
|
// Function: WeakPointerToBase::output
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -83,6 +83,7 @@ public:
|
|||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE void clear();
|
INLINE void clear();
|
||||||
|
INLINE void refresh() const;
|
||||||
|
|
||||||
void output(ostream &out) 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);
|
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);
|
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
|
// Finally, if any of our remaining children are plain PandaNodes
|
||||||
// with no children, just remove them.
|
// 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) {
|
for (int i = parent_node->get_num_children() - 1; i >= 0; --i) {
|
||||||
PandaNode *child_node = parent_node->get_child(i);
|
PandaNode *child_node = parent_node->get_child(i);
|
||||||
if (child_node->is_exact_type(PandaNode::get_class_type()) &&
|
if (child_node->is_exact_type(PandaNode::get_class_type()) &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user