pgraph characters
This commit is contained in:
parent
1c46006c04
commit
4d552344fe
|
|
@ -9,30 +9,37 @@
|
|||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
||||
#define SOURCES \
|
||||
animBundle.I animBundle.h animBundleNode.I animBundleNode.h \
|
||||
animChannel.I animChannel.h animChannelBase.I \
|
||||
animChannelBase.h animChannelMatrixXfmTable.I \
|
||||
animChannelMatrixXfmTable.h animChannelScalarTable.I \
|
||||
animChannelScalarTable.h animControl.I animControl.N \
|
||||
animControl.h animControlCollection.I \
|
||||
animControlCollection.h animGroup.I animGroup.h auto_bind.h \
|
||||
config_chan.h movingPartBase.I movingPartBase.h \
|
||||
movingPartMatrix.I movingPartMatrix.h movingPartScalar.I \
|
||||
movingPartScalar.h partBundle.I partBundle.N partBundle.h \
|
||||
partBundleNode.I partBundleNode.h partGroup.I partGroup.h \
|
||||
vector_PartGroupStar.h
|
||||
animBundle.I animBundle.h animBundleNode.I animBundleNode.h \
|
||||
qpanimBundleNode.I qpanimBundleNode.h \
|
||||
animChannel.I animChannel.h animChannelBase.I \
|
||||
animChannelBase.h animChannelMatrixXfmTable.I \
|
||||
animChannelMatrixXfmTable.h animChannelScalarTable.I \
|
||||
animChannelScalarTable.h animControl.I animControl.N \
|
||||
animControl.h animControlCollection.I \
|
||||
animControlCollection.h animGroup.I animGroup.h auto_bind.h \
|
||||
config_chan.h movingPartBase.I movingPartBase.h \
|
||||
movingPartMatrix.I movingPartMatrix.h movingPartScalar.I \
|
||||
movingPartScalar.h partBundle.I partBundle.N partBundle.h \
|
||||
partBundleNode.I partBundleNode.h \
|
||||
qppartBundleNode.I qppartBundleNode.h \
|
||||
partGroup.I partGroup.h \
|
||||
vector_PartGroupStar.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
animBundle.cxx animBundleNode.cxx animChannel.cxx \
|
||||
animChannelBase.cxx animChannelMatrixXfmTable.cxx \
|
||||
animChannelScalarTable.cxx animControl.cxx \
|
||||
animControlCollection.cxx animGroup.cxx auto_bind.cxx \
|
||||
config_chan.cxx movingPartBase.cxx movingPartMatrix.cxx \
|
||||
movingPartScalar.cxx partBundle.cxx partBundleNode.cxx \
|
||||
partGroup.cxx vector_PartGroupStar.cxx
|
||||
animBundle.cxx animBundleNode.cxx \
|
||||
qpanimBundleNode.cxx \
|
||||
animChannel.cxx \
|
||||
animChannelBase.cxx animChannelMatrixXfmTable.cxx \
|
||||
animChannelScalarTable.cxx animControl.cxx \
|
||||
animControlCollection.cxx animGroup.cxx auto_bind.cxx \
|
||||
config_chan.cxx movingPartBase.cxx movingPartMatrix.cxx \
|
||||
movingPartScalar.cxx partBundle.cxx partBundleNode.cxx \
|
||||
qppartBundleNode.cxx \
|
||||
partGroup.cxx vector_PartGroupStar.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
animBundle.I animBundle.h animBundleNode.I animBundleNode.h \
|
||||
qpanimBundleNode.I qpanimBundleNode.h \
|
||||
animChannel.I animChannel.h animChannelBase.I animChannelBase.h \
|
||||
animChannelFixed.I animChannelFixed.h animChannelMatrixXfmTable.I \
|
||||
animChannelMatrixXfmTable.h animChannelScalarTable.I \
|
||||
|
|
@ -42,7 +49,9 @@
|
|||
movingPart.I movingPart.h movingPartBase.I \
|
||||
movingPartBase.h movingPartMatrix.I movingPartMatrix.h \
|
||||
movingPartScalar.I movingPartScalar.h partBundle.I partBundle.h \
|
||||
partBundleNode.I partBundleNode.h partGroup.I partGroup.h \
|
||||
partBundleNode.I partBundleNode.h \
|
||||
qppartBundleNode.I qppartBundleNode.h \
|
||||
partGroup.I partGroup.h \
|
||||
vector_PartGroupStar.h
|
||||
|
||||
#define IGATESCAN all
|
||||
|
|
|
|||
|
|
@ -17,17 +17,19 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "auto_bind.h"
|
||||
#include "qpanimBundleNode.h"
|
||||
#include "qppartBundleNode.h"
|
||||
#include "config_chan.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
#include "animBundleNode.h"
|
||||
#include "partBundleNode.h"
|
||||
#include "config_chan.h"
|
||||
|
||||
#include <renderRelation.h>
|
||||
#include <traverserVisitor.h>
|
||||
#include <dftraverser.h>
|
||||
#include <string_utils.h>
|
||||
#include <nullLevelState.h>
|
||||
#include <nullTransitionWrapper.h>
|
||||
#include "auto_bind.h"
|
||||
#include "renderRelation.h"
|
||||
#include "traverserVisitor.h"
|
||||
#include "dftraverser.h"
|
||||
#include "nullLevelState.h"
|
||||
#include "nullTransitionWrapper.h"
|
||||
|
||||
typedef pset<AnimBundleNode *> AnimNodes;
|
||||
typedef pmap<string, AnimNodes> Anims;
|
||||
|
|
@ -36,7 +38,6 @@ typedef pset<PartBundleNode *> PartNodes;
|
|||
typedef pmap<string, PartNodes> Parts;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CollectNodes
|
||||
// Description : This is a traverser visitor that locates bundle nodes
|
||||
|
|
@ -133,8 +134,9 @@ bind_anims(const PartNodes &parts, const AnimNodes &anims,
|
|||
// The list of all resulting AnimControls created is
|
||||
// filled into controls.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void auto_bind(Node *root_node, AnimControlCollection &controls,
|
||||
int hierarchy_match_flags) {
|
||||
void
|
||||
auto_bind(Node *root_node, AnimControlCollection &controls,
|
||||
int hierarchy_match_flags) {
|
||||
|
||||
// First, locate all the bundles in the subgraph.
|
||||
CollectNodes cn;
|
||||
|
|
@ -169,3 +171,139 @@ void auto_bind(Node *root_node, AnimControlCollection &controls,
|
|||
}
|
||||
|
||||
|
||||
typedef pset<qpAnimBundleNode *> qpAnimNodes;
|
||||
typedef pmap<string, qpAnimNodes> qpAnims;
|
||||
|
||||
typedef pset<qpPartBundleNode *> qpPartNodes;
|
||||
typedef pmap<string, qpPartNodes> qpParts;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: bind_anims
|
||||
// Description: A support function for auto_bind(), below. Given a
|
||||
// set of AnimBundles and a set of PartBundles that all
|
||||
// share the same name, perform whatever bindings make
|
||||
// sense.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static void
|
||||
qpbind_anims(const qpPartNodes &parts, const qpAnimNodes &anims,
|
||||
AnimControlCollection &controls,
|
||||
int hierarchy_match_flags) {
|
||||
|
||||
qpPartNodes::const_iterator pni;
|
||||
|
||||
for (pni = parts.begin(); pni != parts.end(); ++pni) {
|
||||
PartBundle *part = (*pni)->get_bundle();
|
||||
|
||||
qpAnimNodes::const_iterator ani;
|
||||
for (ani = anims.begin(); ani != anims.end(); ++ani) {
|
||||
AnimBundle *anim = (*ani)->get_bundle();
|
||||
|
||||
if (chan_cat.is_info()) {
|
||||
chan_cat.info()
|
||||
<< "Attempting to bind " << *part << " to " << *anim << "\n";
|
||||
}
|
||||
|
||||
PT(AnimControl) control =
|
||||
part->bind_anim(anim, hierarchy_match_flags);
|
||||
string name = anim->get_name();
|
||||
if (control != (AnimControl *)NULL) {
|
||||
if (controls.find_anim(name) != (AnimControl *)NULL) {
|
||||
// That name's already used; synthesize another one.
|
||||
int index = 0;
|
||||
string new_name;
|
||||
do {
|
||||
index++;
|
||||
new_name = name + '.' + format_string(index);
|
||||
} while (controls.find_anim(new_name) != (AnimControl *)NULL);
|
||||
name = new_name;
|
||||
}
|
||||
|
||||
controls.store_anim(control, name);
|
||||
}
|
||||
|
||||
if (chan_cat.is_info()) {
|
||||
if (control == NULL) {
|
||||
chan_cat.info()
|
||||
<< "Bind failed.\n";
|
||||
} else {
|
||||
chan_cat.info()
|
||||
<< "Bind succeeded, index "
|
||||
<< control->get_channel_index() << "; accessible as "
|
||||
<< name << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: r_find_bundles
|
||||
// Description: A support function for auto_bind(), below. Walks
|
||||
// through the hierarchy and finds all of the
|
||||
// PartBundles and AnimBundles.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static void
|
||||
r_find_bundles(PandaNode *node, qpAnims &anims, qpParts &parts) {
|
||||
if (node->is_of_type(qpAnimBundleNode::get_class_type())) {
|
||||
qpAnimBundleNode *bn = DCAST(qpAnimBundleNode, node);
|
||||
anims[bn->get_bundle()->get_name()].insert(bn);
|
||||
|
||||
} else if (node->is_of_type(qpPartBundleNode::get_class_type())) {
|
||||
qpPartBundleNode *bn = DCAST(qpPartBundleNode, node);
|
||||
parts[bn->get_bundle()->get_name()].insert(bn);
|
||||
}
|
||||
|
||||
PandaNode::Children cr = node->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
r_find_bundles(cr.get_child(i), anims, parts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: auto_bind
|
||||
// Description: Walks the scene graph or subgraph beginning at the
|
||||
// indicated node, and attempts to bind any AnimBundles
|
||||
// found to their matching PartBundles, when possible.
|
||||
//
|
||||
// The list of all resulting AnimControls created is
|
||||
// filled into controls.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
auto_bind(PandaNode *root_node, AnimControlCollection &controls,
|
||||
int hierarchy_match_flags) {
|
||||
// First, locate all the bundles in the subgraph.
|
||||
qpAnims anims;
|
||||
qpParts parts;
|
||||
r_find_bundles(root_node, anims, parts);
|
||||
|
||||
// Now, match up the bundles by name.
|
||||
|
||||
qpAnims::const_iterator ai = anims.begin();
|
||||
qpParts::const_iterator pi = parts.begin();
|
||||
|
||||
while (ai != anims.end() && pi != parts.end()) {
|
||||
if ((*ai).first < (*pi).first) {
|
||||
// Here's an anim with no matching parts.
|
||||
++ai;
|
||||
|
||||
} else if ((*pi).first < (*ai).first) {
|
||||
// And here's a part with no matching anims.
|
||||
++pi;
|
||||
|
||||
} else {
|
||||
// But here we have (at least one) match!
|
||||
qpbind_anims((*pi).second, (*ai).second, controls,
|
||||
hierarchy_match_flags);
|
||||
++pi;
|
||||
|
||||
// We don't increment the anim counter yet. That way, the same
|
||||
// anim may bind to multiple parts, if they all share the same
|
||||
// name.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "animControlCollection.h"
|
||||
|
||||
class Node;
|
||||
class PandaNode;
|
||||
|
||||
BEGIN_PUBLISH
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -39,6 +40,10 @@ BEGIN_PUBLISH
|
|||
EXPCL_PANDA void
|
||||
auto_bind(Node *root_node, AnimControlCollection &controls,
|
||||
int hierarchy_match_flags = 0);
|
||||
|
||||
EXPCL_PANDA void
|
||||
auto_bind(PandaNode *root_node, AnimControlCollection &controls,
|
||||
int hierarchy_match_flags = 0);
|
||||
END_PUBLISH
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "movingPartScalar.cxx"
|
||||
#include "partBundle.cxx"
|
||||
#include "partBundleNode.cxx"
|
||||
#include "qppartBundleNode.cxx"
|
||||
#include "partGroup.cxx"
|
||||
#include "vector_PartGroupStar.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include "animBundle.cxx"
|
||||
#include "animBundleNode.cxx"
|
||||
#include "qpanimBundleNode.cxx"
|
||||
#include "animChannel.cxx"
|
||||
#include "animChannelBase.cxx"
|
||||
#include "animChannelMatrixXfmTable.cxx"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "config_chan.h"
|
||||
#include "animBundle.h"
|
||||
#include "animBundleNode.h"
|
||||
#include "qpanimBundleNode.h"
|
||||
#include "animChannelBase.h"
|
||||
#include "animChannelMatrixXfmTable.h"
|
||||
#include "animChannelScalarTable.h"
|
||||
|
|
@ -30,10 +31,11 @@
|
|||
#include "movingPartScalar.h"
|
||||
#include "partBundle.h"
|
||||
#include "partBundleNode.h"
|
||||
#include "qppartBundleNode.h"
|
||||
#include "partGroup.h"
|
||||
|
||||
#include <luse.h>
|
||||
#include <dconfig.h>
|
||||
#include "luse.h"
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_chan);
|
||||
NotifyCategoryDef(chan, "");
|
||||
|
|
@ -79,6 +81,7 @@ bool read_compressed_channels = config_chan.GetBool("read-compressed-channels",
|
|||
ConfigureFn(config_chan) {
|
||||
AnimBundle::init_type();
|
||||
AnimBundleNode::init_type();
|
||||
qpAnimBundleNode::init_type();
|
||||
AnimChannelBase::init_type();
|
||||
AnimChannelMatrixXfmTable::init_type();
|
||||
AnimChannelScalarTable::init_type();
|
||||
|
|
@ -89,6 +92,7 @@ ConfigureFn(config_chan) {
|
|||
MovingPartScalar::init_type();
|
||||
PartBundle::init_type();
|
||||
PartBundleNode::init_type();
|
||||
qpPartBundleNode::init_type();
|
||||
PartGroup::init_type();
|
||||
|
||||
// This isn't defined in this package, but it *is* essential that it
|
||||
|
|
@ -107,6 +111,7 @@ ConfigureFn(config_chan) {
|
|||
AnimGroup::register_with_read_factory();
|
||||
AnimBundle::register_with_read_factory();
|
||||
AnimBundleNode::register_with_read_factory();
|
||||
qpAnimBundleNode::register_with_read_factory();
|
||||
AnimChannelMatrixXfmTable::register_with_read_factory();
|
||||
AnimChannelScalarTable::register_with_read_factory();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,17 @@ get_node() const {
|
|||
return _node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::get_qpnode
|
||||
// Access: Published
|
||||
// Description: Returns the PartBundleNode associated with this
|
||||
// PartBundle.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpPartBundleNode *PartBundle::
|
||||
get_qpnode() const {
|
||||
return _qpnode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::control_begin
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -19,17 +19,18 @@
|
|||
#ifndef PARTBUNDLE_H
|
||||
#define PARTBUNDLE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "partGroup.h"
|
||||
#include "animControl.h"
|
||||
#include "animControlCollection.h"
|
||||
|
||||
#include <pointerTo.h>
|
||||
#include <iterator_types.h>
|
||||
#include "pointerTo.h"
|
||||
#include "iterator_types.h"
|
||||
|
||||
class AnimBundle;
|
||||
class PartBundleNode;
|
||||
class qpPartBundleNode;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PartBundle
|
||||
|
|
@ -93,6 +94,7 @@ PUBLISHED:
|
|||
INLINE BlendType get_blend_type() const;
|
||||
|
||||
INLINE PartBundleNode *get_node() const;
|
||||
INLINE qpPartBundleNode *get_qpnode() const;
|
||||
|
||||
void clear_control_effects();
|
||||
void set_control_effect(AnimControl *control, float effect);
|
||||
|
|
@ -131,6 +133,7 @@ protected:
|
|||
|
||||
BlendType _blend_type;
|
||||
PartBundleNode *_node;
|
||||
qpPartBundleNode *_qpnode;
|
||||
|
||||
AnimControl *_last_control_set;
|
||||
ChannelBlend _blend;
|
||||
|
|
@ -162,6 +165,7 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
|
||||
friend class PartBundleNode;
|
||||
friend class qpPartBundleNode;
|
||||
};
|
||||
|
||||
inline ostream &operator <<(ostream &out, const PartBundle &bundle) {
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Character;
|
||||
friend class qpCharacter;
|
||||
};
|
||||
|
||||
#include "partGroup.I"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
// Filename: qpanimBundleNode.I
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::Constructor
|
||||
// Access: Public
|
||||
// Description: The AnimBundle and its node should be constructed
|
||||
// together. Generally, the derived classes of
|
||||
// qpAnimBundleNode will automatically create a AnimBundle
|
||||
// of the appropriate type, and pass it up to this
|
||||
// constructor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpAnimBundleNode::
|
||||
qpAnimBundleNode(const string &name, AnimBundle *bundle) :
|
||||
PandaNode(name),
|
||||
_bundle(bundle)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::Default Constructor
|
||||
// Access: Protected
|
||||
// Description: For internal use only.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpAnimBundleNode::
|
||||
qpAnimBundleNode() : PandaNode("") {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::Copy Constructor
|
||||
// Access: Protected
|
||||
// Description: Use make_copy() or copy_subgraph() to copy one of
|
||||
// these. Copying a qpAnimBundleNode will always force a
|
||||
// deep copy of the PartGroup hierarchy.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpAnimBundleNode::
|
||||
qpAnimBundleNode(const qpAnimBundleNode ©) :
|
||||
PandaNode(copy),
|
||||
_bundle(copy._bundle)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::get_bundle
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AnimBundle *qpAnimBundleNode::
|
||||
get_bundle() const {
|
||||
return _bundle;
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// Filename: qpanimBundleNode.cxx
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qpanimBundleNode.h"
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
|
||||
TypeHandle qpAnimBundleNode::_type_handle;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::safe_to_flatten
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if it is generally safe to flatten out
|
||||
// this particular kind of Node by duplicating
|
||||
// instances, false otherwise (for instance, a Camera
|
||||
// cannot be safely flattened, because the Camera
|
||||
// pointer itself is meaningful).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpAnimBundleNode::
|
||||
safe_to_flatten() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// qpAnimBundleNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpAnimBundleNode::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpAnimBundleNode::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
PandaNode::write_datagram(manager, dg);
|
||||
manager->write_pointer(dg, _bundle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::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 qpAnimBundleNode::
|
||||
complete_pointers(TypedWritable **p_list, BamReader* manager) {
|
||||
int pi = PandaNode::complete_pointers(p_list, manager);
|
||||
_bundle = DCAST(AnimBundle, p_list[pi++]);
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of this type is encountered
|
||||
// in the Bam file. It should create the object
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *qpAnimBundleNode::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
qpAnimBundleNode *node = new qpAnimBundleNode;
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpAnimBundleNode::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 PandaNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpAnimBundleNode::
|
||||
fillin(DatagramIterator &scan, BamReader* manager) {
|
||||
PandaNode::fillin(scan, manager);
|
||||
manager->read_pointer(scan, this);
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
// Filename: qpanimBundleNode.h
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef qpANIMBUNDLENODE_H
|
||||
#define qpANIMBUNDLENODE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "animBundle.h"
|
||||
|
||||
#include "pandaNode.h"
|
||||
#include "dcast.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpAnimBundleNode
|
||||
// Description : This is a node that contains a pointer to an
|
||||
// AnimBundle. Like AnimBundleNode, it exists solely to
|
||||
// make it easy to store AnimBundles in the scene graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA qpAnimBundleNode : public PandaNode {
|
||||
public:
|
||||
INLINE qpAnimBundleNode(const string &name, AnimBundle *bundle);
|
||||
|
||||
protected:
|
||||
INLINE qpAnimBundleNode();
|
||||
INLINE qpAnimBundleNode(const qpAnimBundleNode ©);
|
||||
|
||||
public:
|
||||
virtual bool safe_to_flatten() const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE AnimBundle *get_bundle() const;
|
||||
|
||||
private:
|
||||
PT(AnimBundle) _bundle;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter* manager, Datagram &me);
|
||||
virtual int complete_pointers(TypedWritable **p_list,
|
||||
BamReader *manager);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator& scan, BamReader* manager);
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
PandaNode::init_type();
|
||||
register_type(_type_handle, "qpAnimBundleNode",
|
||||
PandaNode::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "qpanimBundleNode.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
// Filename: qppartBundleNode.I
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::Constructor
|
||||
// Access: Public
|
||||
// Description: The PartBundle and its node should be constructed
|
||||
// together. Generally, the derived classes of
|
||||
// qpPartBundleNode will automatically create a PartBundle
|
||||
// of the appropriate type, and pass it up to this
|
||||
// constructor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpPartBundleNode::
|
||||
qpPartBundleNode(const string &name, PartBundle *bundle) :
|
||||
PandaNode(name),
|
||||
_bundle(bundle)
|
||||
{
|
||||
_bundle->_qpnode = this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::Default Constructor
|
||||
// Access: Protected
|
||||
// Description: For internal use only.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpPartBundleNode::
|
||||
qpPartBundleNode() : PandaNode("") {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::Copy Constructor
|
||||
// Access: Protected
|
||||
// Description: Use make_copy() or copy_subgraph() to copy one of
|
||||
// these. Copying a qpPartBundleNode will always force a
|
||||
// deep copy of the PartGroup hierarchy.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpPartBundleNode::
|
||||
qpPartBundleNode(const qpPartBundleNode ©) :
|
||||
PandaNode(copy),
|
||||
_bundle(DCAST(PartBundle, copy._bundle->copy_subgraph()))
|
||||
{
|
||||
_bundle->_qpnode = this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::get_bundle
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundle *qpPartBundleNode::
|
||||
get_bundle() const {
|
||||
return _bundle;
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// Filename: qppartBundleNode.cxx
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qppartBundleNode.h"
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
|
||||
TypeHandle qpPartBundleNode::_type_handle;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::safe_to_flatten
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if it is generally safe to flatten out
|
||||
// this particular kind of Node by duplicating
|
||||
// instances, false otherwise (for instance, a Camera
|
||||
// cannot be safely flattened, because the Camera
|
||||
// pointer itself is meaningful).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpPartBundleNode::
|
||||
safe_to_flatten() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpPartBundleNode::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
PandaNode::write_datagram(manager, dg);
|
||||
manager->write_pointer(dg, _bundle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::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 qpPartBundleNode::
|
||||
complete_pointers(TypedWritable **p_list, BamReader* manager) {
|
||||
int pi = PandaNode::complete_pointers(p_list, manager);
|
||||
_bundle = DCAST(PartBundle, p_list[pi++]);
|
||||
_bundle->_qpnode = this;
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpPartBundleNode::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 PandaNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpPartBundleNode::
|
||||
fillin(DatagramIterator &scan, BamReader* manager) {
|
||||
PandaNode::fillin(scan, manager);
|
||||
manager->read_pointer(scan, this);
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// Filename: qppartBundleNode.h
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef qpPARTBUNDLENODE_H
|
||||
#define qpPARTBUNDLENODE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "partBundle.h"
|
||||
|
||||
#include "pandaNode.h"
|
||||
#include "dcast.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpPartBundleNode
|
||||
// Description : This is a node that contains a pointer to an
|
||||
// PartBundle. Like AnimBundleNode, it exists solely to
|
||||
// make it easy to store PartBundles in the scene graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA qpPartBundleNode : public PandaNode {
|
||||
public:
|
||||
INLINE qpPartBundleNode(const string &name, PartBundle *bundle);
|
||||
|
||||
protected:
|
||||
INLINE qpPartBundleNode();
|
||||
INLINE qpPartBundleNode(const qpPartBundleNode ©);
|
||||
|
||||
public:
|
||||
virtual bool safe_to_flatten() const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE PartBundle *get_bundle() const;
|
||||
|
||||
private:
|
||||
PT(PartBundle) _bundle;
|
||||
|
||||
public:
|
||||
virtual void write_datagram(BamWriter* manager, Datagram &me);
|
||||
virtual int complete_pointers(TypedWritable **p_list,
|
||||
BamReader *manager);
|
||||
|
||||
protected:
|
||||
void fillin(DatagramIterator& scan, BamReader* manager);
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
PandaNode::init_type();
|
||||
register_type(_type_handle, "qpPartBundleNode",
|
||||
PandaNode::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "qppartBundleNode.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -10,19 +10,25 @@
|
|||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
||||
#define SOURCES \
|
||||
character.I character.h characterJoint.h characterJointBundle.I \
|
||||
characterJointBundle.h characterSlider.h computedVertices.I \
|
||||
computedVertices.h computedVerticesMorph.I \
|
||||
computedVerticesMorph.h config_char.h dynamicVertices.h
|
||||
character.I character.h \
|
||||
qpcharacter.I qpcharacter.h \
|
||||
characterJoint.h characterJointBundle.I \
|
||||
characterJointBundle.h characterSlider.h computedVertices.I \
|
||||
computedVertices.h computedVerticesMorph.I \
|
||||
computedVerticesMorph.h config_char.h dynamicVertices.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
character.cxx characterJoint.cxx characterJointBundle.cxx \
|
||||
characterSlider.cxx computedVertices.cxx \
|
||||
computedVerticesMorph.cxx config_char.cxx \
|
||||
dynamicVertices.cxx
|
||||
character.cxx \
|
||||
qpcharacter.cxx \
|
||||
characterJoint.cxx characterJointBundle.cxx \
|
||||
characterSlider.cxx computedVertices.cxx \
|
||||
computedVerticesMorph.cxx config_char.cxx \
|
||||
dynamicVertices.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
character.I character.h characterJoint.h characterJointBundle.I \
|
||||
character.I character.h \
|
||||
qpcharacter.I qpcharacter.h \
|
||||
characterJoint.h characterJointBundle.I \
|
||||
characterJointBundle.h characterSlider.h computedVertices.I \
|
||||
computedVertices.h computedVerticesMorph.I computedVerticesMorph.h \
|
||||
config_char.h dynamicVertices.h
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include "config_char.cxx"
|
||||
#include "character.cxx"
|
||||
#include "qpcharacter.cxx"
|
||||
#include "characterJoint.cxx"
|
||||
#include "characterJointBundle.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ public:
|
|||
// character. It does not store any meaningful value after
|
||||
// creation is complete.
|
||||
PT_NamedNode _geom_node;
|
||||
PT(PandaNode) _qpgeom_node;
|
||||
|
||||
// These are filled in as the joint animates.
|
||||
LMatrix4f _net_transform;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "computedVertices.h"
|
||||
#include "characterJoint.h"
|
||||
#include "character.h"
|
||||
#include "qpcharacter.h"
|
||||
#include "config_char.h"
|
||||
|
||||
#include <datagram.h>
|
||||
|
|
@ -53,28 +54,29 @@ VertexTransform(const VertexTransform ©) :
|
|||
// vertices in the table, according to the values of the
|
||||
// relevant slider.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class ValueType, class MorphType>
|
||||
// QP
|
||||
template<class ValueType, class MorphType, class Character>
|
||||
static void
|
||||
compute_morphs(ValueType *table, const pvector<MorphType> &morph_list,
|
||||
Character *character) {
|
||||
Character *character) {
|
||||
pvector<MorphType>::const_iterator mli;
|
||||
for (mli = morph_list.begin(); mli != morph_list.end(); ++mli) {
|
||||
const MorphType &morph = (*mli);
|
||||
const CharacterSlider *slider;
|
||||
DCAST_INTO_V(slider, character->get_part(morph._slider_index));
|
||||
|
||||
|
||||
float slider_value = slider->_value;
|
||||
|
||||
|
||||
if (slider_value != 0.0f) {
|
||||
typedef TYPENAME MorphType::Morphs Morphs;
|
||||
typedef TYPENAME MorphType::MorphValue MorphValue;
|
||||
TYPENAME Morphs::const_iterator mi;
|
||||
for (mi = morph._morphs.begin(); mi != morph._morphs.end(); ++mi) {
|
||||
typedef typename MorphValue::VecType VecType;
|
||||
ushort index = (*mi)._index;
|
||||
const VecType &v = (*mi)._vector;
|
||||
|
||||
table[index] += v * slider_value;
|
||||
typedef typename MorphValue::VecType VecType;
|
||||
ushort index = (*mi)._index;
|
||||
const VecType &v = (*mi)._vector;
|
||||
|
||||
table[index] += v * slider_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,6 +231,108 @@ update(Character *character) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ComputedVertices::update
|
||||
// Access: Public
|
||||
// Description: Recomputes all of the _coords, _norms, etc. values
|
||||
// based on the values in _orig_coords, _orig_norms,
|
||||
// etc., and the current positions of all of the joints.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ComputedVertices::
|
||||
update(qpCharacter *character) {
|
||||
nassertv(character != (qpCharacter *)NULL);
|
||||
nassertv(character->_cv._coords.size() == _orig_coords.size());
|
||||
nassertv(character->_cv._norms.size() == _orig_norms.size());
|
||||
nassertv(character->_cv._texcoords.size() == _orig_texcoords.size());
|
||||
nassertv(character->_cv._colors.size() == _orig_colors.size());
|
||||
|
||||
const Vertexf *orig_coords = _orig_coords;
|
||||
const Normalf *orig_norms = _orig_norms;
|
||||
|
||||
memset(character->_cv._coords, 0, sizeof(Vertexf) * character->_cv._coords.size());
|
||||
memset(character->_cv._norms, 0, sizeof(Normalf) * character->_cv._norms.size());
|
||||
|
||||
if (!_vertex_morphs.empty()) {
|
||||
// We have some vertex morphs. Compute them first.
|
||||
int table_size = sizeof(Vertexf) * _orig_coords.size();
|
||||
Vertexf *morphed_coords = (Vertexf *)alloca(table_size);
|
||||
memcpy(morphed_coords, _orig_coords, table_size);
|
||||
|
||||
compute_morphs(morphed_coords, _vertex_morphs, character);
|
||||
orig_coords = morphed_coords;
|
||||
}
|
||||
|
||||
if (!_normal_morphs.empty()) {
|
||||
// We also have some normal morphs. Compute them too.
|
||||
int table_size = sizeof(Normalf) * _orig_norms.size();
|
||||
Normalf *morphed_norms = (Normalf *)alloca(table_size);
|
||||
memcpy(morphed_norms, _orig_norms, table_size);
|
||||
|
||||
compute_morphs(morphed_norms, _normal_morphs, character);
|
||||
orig_norms = morphed_norms;
|
||||
}
|
||||
|
||||
if (!_texcoord_morphs.empty()) {
|
||||
// We have some uv morphs. These don't particularly need to be
|
||||
// done before the joints are computed, but do them now anyway.
|
||||
int table_size = sizeof(TexCoordf) * _orig_texcoords.size();
|
||||
|
||||
// **** Is this right? Test it!
|
||||
// TexCoordf *morphed_texcoords = (TexCoordf *)alloca(table_size);
|
||||
memcpy(character->_cv._texcoords, _orig_texcoords, table_size);
|
||||
|
||||
compute_morphs(character->_cv._texcoords.p(), _texcoord_morphs, character);
|
||||
}
|
||||
|
||||
if (!_color_morphs.empty()) {
|
||||
// We have some color morphs. Do these now too.
|
||||
int table_size = sizeof(Colorf) * _orig_colors.size();
|
||||
|
||||
// **** Is this right? Test it!
|
||||
// Colorf *morphed_colors = (Colorf *)alloca(table_size);
|
||||
memcpy(character->_cv._colors, _orig_colors, table_size);
|
||||
|
||||
compute_morphs(character->_cv._colors.p(), _color_morphs, character);
|
||||
}
|
||||
|
||||
// Now that we've computed all the morphs, it's safe to transform
|
||||
// vertices into their proper coordinate space, according to the
|
||||
// current positions of all the joints.
|
||||
|
||||
LMatrix4f mat = LMatrix4f::ident_mat();
|
||||
int last_joint_index = -1;
|
||||
|
||||
VertexTransforms::const_iterator vti;
|
||||
for (vti = _transforms.begin(); vti != _transforms.end(); ++vti) {
|
||||
const VertexTransform &vt = (*vti);
|
||||
|
||||
// We cache the matrix from the last joint, because we are likely
|
||||
// to encounter the same joint several times in a row.
|
||||
if (vt._joint_index != last_joint_index) {
|
||||
last_joint_index = vt._joint_index;
|
||||
|
||||
// We won't encounter -1 after the first few joints.
|
||||
nassertv(vt._joint_index >= 0);
|
||||
CharacterJoint *joint;
|
||||
DCAST_INTO_V(joint, character->get_part(vt._joint_index));
|
||||
|
||||
mat =
|
||||
joint->_initial_net_transform_inverse *
|
||||
joint->_net_transform;
|
||||
}
|
||||
|
||||
Vertices::const_iterator vi;
|
||||
for (vi = vt._vindex.begin(); vi != vt._vindex.end(); ++vi) {
|
||||
int i = (*vi);
|
||||
character->_cv._coords[i] += (orig_coords[i] * mat) * vt._effect;
|
||||
}
|
||||
for (vi = vt._nindex.begin(); vi != vt._nindex.end(); ++vi) {
|
||||
int i = (*vi);
|
||||
character->_cv._norms[i] += (orig_norms[i] * mat) * vt._effect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ComputedVertices::make_orig
|
||||
// Access: Public
|
||||
|
|
@ -269,6 +373,46 @@ make_orig(Character *character) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ComputedVertices::make_orig
|
||||
// Access: Public
|
||||
// Description: Copies all the values loaded in the _coords, _norms,
|
||||
// etc. arrays into the corresponding _orig_coords,
|
||||
// etc. arrays.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ComputedVertices::
|
||||
make_orig(qpCharacter *character) {
|
||||
nassertv(character != (qpCharacter *)NULL);
|
||||
|
||||
if (character->_cv._coords.empty()) {
|
||||
_orig_coords.clear();
|
||||
} else {
|
||||
_orig_coords = PTA_Vertexf::empty_array(0);
|
||||
_orig_coords.v() = character->_cv._coords.v();
|
||||
}
|
||||
|
||||
if (character->_cv._norms.empty()) {
|
||||
_orig_norms.clear();
|
||||
} else {
|
||||
_orig_norms = PTA_Normalf::empty_array(0);
|
||||
_orig_norms.v() = character->_cv._norms.v();
|
||||
}
|
||||
|
||||
if (character->_cv._colors.empty()) {
|
||||
_orig_colors.clear();
|
||||
} else {
|
||||
_orig_colors = PTA_Colorf::empty_array(0);
|
||||
_orig_colors.v() = character->_cv._colors.v();
|
||||
}
|
||||
|
||||
if (character->_cv._texcoords.empty()) {
|
||||
_orig_texcoords.clear();
|
||||
} else {
|
||||
_orig_texcoords = PTA_TexCoordf::empty_array(0);
|
||||
_orig_texcoords.v() = character->_cv._texcoords.v();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ComputedVertices::write
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -19,15 +19,16 @@
|
|||
#ifndef COMPUTEDVERTICES_H
|
||||
#define COMPUTEDVERTICES_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "dynamicVertices.h"
|
||||
#include "computedVerticesMorph.h"
|
||||
|
||||
#include <vector_ushort.h>
|
||||
#include <typedWritableReferenceCount.h>
|
||||
#include "vector_ushort.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
|
||||
class Character;
|
||||
class qpCharacter;
|
||||
class CharacterJoint;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -42,7 +43,9 @@ public:
|
|||
INLINE ComputedVertices();
|
||||
|
||||
void update(Character *character);
|
||||
void update(qpCharacter *character);
|
||||
void make_orig(Character *character);
|
||||
void make_orig(qpCharacter *character);
|
||||
|
||||
void write(ostream &out, Character *character) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "config_char.h"
|
||||
#include "character.h"
|
||||
#include "qpcharacter.h"
|
||||
#include "characterJoint.h"
|
||||
#include "characterJointBundle.h"
|
||||
#include "characterSlider.h"
|
||||
|
|
@ -67,6 +68,7 @@ init_libchar() {
|
|||
initialized = true;
|
||||
|
||||
Character::init_type();
|
||||
qpCharacter::init_type();
|
||||
CharacterJoint::init_type();
|
||||
CharacterJointBundle::init_type();
|
||||
CharacterSlider::init_type();
|
||||
|
|
@ -82,6 +84,7 @@ init_libchar() {
|
|||
//Registration of writeable object's creation
|
||||
//functions with BamReader's factory
|
||||
Character::register_with_read_factory();
|
||||
qpCharacter::register_with_read_factory();
|
||||
CharacterJoint::register_with_read_factory();
|
||||
CharacterJointBundle::register_with_read_factory();
|
||||
CharacterSlider::register_with_read_factory();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
// Filename: qpcharacter.I
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "characterJointBundle.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::get_bundle
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CharacterJointBundle *qpCharacter::
|
||||
get_bundle() const {
|
||||
return DCAST(CharacterJointBundle, qpPartBundleNode::get_bundle());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::get_computed_vertices
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ComputedVertices *qpCharacter::
|
||||
get_computed_vertices() const {
|
||||
return _computed_vertices;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::get_num_parts
|
||||
// Access: Public
|
||||
// Description: Returns the total number of moving parts (e.g. joints
|
||||
// and sliders) associated with the qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpCharacter::
|
||||
get_num_parts() const {
|
||||
return _parts.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::get_part
|
||||
// Access: Public
|
||||
// Description: Returns the nth moving part associated with the
|
||||
// qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartGroup *qpCharacter::
|
||||
get_part(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_parts.size(), NULL);
|
||||
return _parts[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::write_parts
|
||||
// Access: Public
|
||||
// Description: Writes a list of the qpCharacter's joints and sliders,
|
||||
// in their hierchical structure, to the indicated
|
||||
// output stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpCharacter::
|
||||
write_parts(ostream &out) const {
|
||||
get_bundle()->write(out, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::write_part_values
|
||||
// Access: Public
|
||||
// Description: Writes a list of the qpCharacter's joints and sliders,
|
||||
// along with each current position, in their hierchical
|
||||
// structure, to the indicated output stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpCharacter::
|
||||
write_part_values(ostream &out) const {
|
||||
get_bundle()->write_with_value(out, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,538 @@
|
|||
// Filename: qpcharacter.cxx
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qpcharacter.h"
|
||||
#include "characterJoint.h"
|
||||
#include "computedVertices.h"
|
||||
#include "config_char.h"
|
||||
|
||||
#include "geomNode.h"
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "geomNode.h"
|
||||
#include "animControl.h"
|
||||
#include "clockObject.h"
|
||||
#include "pStatTimer.h"
|
||||
|
||||
TypeHandle qpCharacter::_type_handle;
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector qpCharacter::_anim_pcollector("App:Animation");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::Copy Constructor
|
||||
// Access: Protected
|
||||
// Description: Use make_copy() or copy_subgraph() to copy a qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpCharacter::
|
||||
qpCharacter(const qpCharacter ©) :
|
||||
qpPartBundleNode(copy.get_name(), new CharacterJointBundle(copy.get_bundle()->get_name())),
|
||||
_cv(DynamicVertices::deep_copy(copy._cv)),
|
||||
_computed_vertices(copy._computed_vertices),
|
||||
_parts(copy._parts),
|
||||
_char_pcollector(copy._char_pcollector)
|
||||
{
|
||||
// Now make a copy of the joint/slider hierarchy. We could just use
|
||||
// the PartBundleNode's copy constructor, but if we do it ourselves
|
||||
// we can simultaneously update our _parts list.
|
||||
|
||||
copy_joints(get_bundle(), copy.get_bundle());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpCharacter::
|
||||
qpCharacter(const string &name) :
|
||||
qpPartBundleNode(name, new CharacterJointBundle(name)),
|
||||
_char_pcollector(_anim_pcollector, name)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpCharacter::
|
||||
~qpCharacter() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description: The qpCharacter make_copy() function will make a new
|
||||
// copy of the qpCharacter, with all of its joints copied,
|
||||
// and with a new set of dynamic vertex arrays all ready
|
||||
// to go, but it will not copy any of the original
|
||||
// qpCharacter's geometry, so the new qpCharacter won't look
|
||||
// like much. Use copy_subgraph() to make a full copy
|
||||
// of the qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode *qpCharacter::
|
||||
make_copy() const {
|
||||
return new qpCharacter(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::safe_to_transform
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if it is generally safe to transform
|
||||
// this particular kind of Node by calling the xform()
|
||||
// method, false otherwise. For instance, it's usually
|
||||
// a bad idea to attempt to xform a qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpCharacter::
|
||||
safe_to_transform() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::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 node during the cull
|
||||
// traversal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpCharacter::
|
||||
has_cull_callback() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::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.
|
||||
//
|
||||
// By the time this function is called, the node has
|
||||
// already passed the bounding-volume test for the
|
||||
// viewing frustum, and the node's transform and state
|
||||
// have already been applied to the indicated
|
||||
// CullTraverserData object.
|
||||
//
|
||||
// The return value is true if this node should be
|
||||
// visible, or false if it should be culled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpCharacter::
|
||||
cull_callback(CullTraverserData &) {
|
||||
// For now, we update the character during the cull traversal; this
|
||||
// prevents us from needlessly updating characters that aren't in
|
||||
// the view frustum. We may need a better way to do this
|
||||
// optimization later, to handle characters that might animate
|
||||
// themselves in front of the view frustum.
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
get_bundle()->advance_time(now);
|
||||
|
||||
if (char_cat.is_spam()) {
|
||||
char_cat.spam() << "Animating " << *this << " at time " << now << "\n";
|
||||
}
|
||||
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::update
|
||||
// Access: Public
|
||||
// Description: Recalculates the qpCharacter's joints and vertices for
|
||||
// the current frame. Normally this is performed
|
||||
// automatically during the render and need not be
|
||||
// called explicitly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCharacter::
|
||||
update() {
|
||||
// Statistics
|
||||
PStatTimer timer(_char_pcollector);
|
||||
|
||||
// First, update all the joints and sliders.
|
||||
bool any_changed = get_bundle()->update();
|
||||
|
||||
// Now update the vertices, if we need to. This is likely to be a
|
||||
// slow operation.
|
||||
if (any_changed || even_animation) {
|
||||
if (_computed_vertices != (ComputedVertices *)NULL) {
|
||||
_computed_vertices->update(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::copy_joints
|
||||
// Access: Private
|
||||
// Description: Recursively walks the joint/slider hierarchy and
|
||||
// creates a new copy of the hierarchy.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCharacter::
|
||||
copy_joints(PartGroup *copy, PartGroup *orig) {
|
||||
if (copy->get_type() != orig->get_type()) {
|
||||
char_cat.warning()
|
||||
<< "Don't know how to copy " << orig->get_type() << "\n";
|
||||
}
|
||||
|
||||
PartGroup::Children::const_iterator ci;
|
||||
for (ci = orig->_children.begin(); ci != orig->_children.end(); ++ci) {
|
||||
PartGroup *orig_child = (*ci);
|
||||
PartGroup *copy_child = orig_child->make_copy();
|
||||
copy->_children.push_back(copy_child);
|
||||
copy_joints(copy_child, orig_child);
|
||||
}
|
||||
|
||||
Parts::iterator pi = find(_parts.begin(), _parts.end(), orig);
|
||||
if (pi != _parts.end()) {
|
||||
(*pi) = copy;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::r_copy_subgraph
|
||||
// Access: Private, Virtual
|
||||
// Description: This is a virtual function inherited from Node. It's
|
||||
// called when a copy_subgraph() operation reaches the
|
||||
// qpCharacter node. In the case of a qpCharacter, it's
|
||||
// overridden to do the all right things to copy the
|
||||
// dynamic geometry to the new qpCharacter.
|
||||
//
|
||||
// Note that it includes the parameter inst_map, which
|
||||
// is a map type, and is not (and cannot be) exported
|
||||
// from PANDA.DLL. Thus, any derivative of Node that is
|
||||
// not also a member of PANDA.DLL *cannot* access this
|
||||
// map.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Node *qpCharacter::
|
||||
r_copy_subgraph(TypeHandle graph_type, Node::InstanceMap &) const {
|
||||
Node *copy = make_copy();
|
||||
nassertr(copy != (Node *)NULL, NULL);
|
||||
if (copy->get_type() != get_type()) {
|
||||
graph_cat.warning()
|
||||
<< "Don't know how to copy nodes of type " << get_type() << "\n";
|
||||
}
|
||||
|
||||
// We assume there will be no instancing going on below the
|
||||
// qpCharacter node. If there is, too bad; it will get flattened out.
|
||||
|
||||
// Now we preempt the node's r_copy_subgraph() operation with our
|
||||
// own function that keeps track of the old vs. new arcs and also
|
||||
// updates any Geoms we find with our new dynamic vertices.
|
||||
|
||||
qpCharacter *char_copy;
|
||||
DCAST_INTO_R(char_copy, copy, NULL);
|
||||
ArcMap arc_map;
|
||||
char_copy->r_copy_char(char_copy, this, graph_type, this, arc_map);
|
||||
char_copy->copy_arc_pointers(this, arc_map);
|
||||
|
||||
return copy;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::r_copy_char
|
||||
// Access: Private
|
||||
// Description: Recursively walks the scene graph hierarchy below the
|
||||
// qpCharacter node, duplicating it while noting the
|
||||
// orig:copy arc mappings, and also updates any
|
||||
// GeomNodes found.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCharacter::
|
||||
r_copy_char(Node *dest, const Node *source, TypeHandle graph_type,
|
||||
const qpCharacter *from, qpCharacter::ArcMap &arc_map) {
|
||||
if (source->is_of_type(GeomNode::get_class_type())) {
|
||||
const GeomNode *source_gnode;
|
||||
GeomNode *dest_gnode;
|
||||
DCAST_INTO_V(source_gnode, source);
|
||||
DCAST_INTO_V(dest_gnode, dest);
|
||||
|
||||
dest_gnode->clear();
|
||||
int num_geoms = source_gnode->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
dDrawable *d = source_gnode->get_geom(i);
|
||||
if (d->is_of_type(Geom::get_class_type())) {
|
||||
dest_gnode->add_geom(copy_geom(DCAST(Geom, d), from));
|
||||
} else {
|
||||
dest_gnode->add_geom(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int num_children = source->get_num_children(graph_type);
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
NodeRelation *source_arc = source->get_child(graph_type, i);
|
||||
const Node *source_child = source_arc->get_child();
|
||||
nassertv(source_child != (Node *)NULL);
|
||||
|
||||
Node *dest_child;
|
||||
if (source_child->is_of_type(qpCharacter::get_class_type())) {
|
||||
// We make a special case for nodes of type qpCharacter. If we
|
||||
// encounter one of these, we have a qpCharacter under a
|
||||
// qpCharacter, and the nested qpCharacter's copy should be called
|
||||
// instead of ours.
|
||||
dest_child = source_child->copy_subgraph(graph_type);
|
||||
|
||||
} else {
|
||||
// Otherwise, we assume that make_copy() will make a suitable
|
||||
// copy of the node. This does limit the sorts of things we can
|
||||
// have parented to a qpCharacter and expect copy_subgraph() to
|
||||
// work correctly. Too bad.
|
||||
dest_child = source_child->make_copy();
|
||||
r_copy_char(dest_child, source_child, graph_type, from, arc_map);
|
||||
}
|
||||
|
||||
NodeRelation *dest_arc =
|
||||
NodeRelation::create_typed_arc(graph_type, dest, dest_child);
|
||||
nassertv(dest_arc != (NodeRelation *)NULL);
|
||||
nassertv(dest_arc->is_exact_type(graph_type));
|
||||
|
||||
dest_arc->copy_transitions_from(source_arc);
|
||||
arc_map[source_arc] = dest_arc;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::copy_geom
|
||||
// Access: Private
|
||||
// Description: Makes a new copy of the Geom with the dynamic vertex
|
||||
// arrays replaced to reference this qpCharacter instead
|
||||
// of the other one. If no arrays have changed, simply
|
||||
// returns the same Geom.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Geom) qpCharacter::
|
||||
copy_geom(Geom *source, const qpCharacter *from) {
|
||||
GeomBindType bind;
|
||||
PTA_ushort index;
|
||||
|
||||
PTA_Vertexf coords;
|
||||
PTA_Normalf norms;
|
||||
PTA_Colorf colors;
|
||||
PTA_TexCoordf texcoords;
|
||||
|
||||
PT(Geom) dest = source;
|
||||
|
||||
source->get_coords(coords, index);
|
||||
if ((coords != (void *)NULL) && (coords == (from->_cv._coords))) {
|
||||
if (dest == source) {
|
||||
dest = source->make_copy();
|
||||
}
|
||||
dest->set_coords(_cv._coords, index);
|
||||
}
|
||||
|
||||
source->get_normals(norms, bind, index);
|
||||
if (bind != G_OFF && norms == from->_cv._norms) {
|
||||
if (dest == source) {
|
||||
dest = source->make_copy();
|
||||
}
|
||||
dest->set_normals(_cv._norms, bind, index);
|
||||
}
|
||||
|
||||
source->get_colors(colors, bind, index);
|
||||
if (bind != G_OFF && colors == from->_cv._colors) {
|
||||
if (dest == source) {
|
||||
dest = source->make_copy();
|
||||
}
|
||||
dest->set_colors(_cv._colors, bind, index);
|
||||
}
|
||||
|
||||
source->get_texcoords(texcoords, bind, index);
|
||||
if (bind != G_OFF && texcoords == from->_cv._texcoords) {
|
||||
if (dest == source) {
|
||||
dest = source->make_copy();
|
||||
}
|
||||
dest->set_texcoords(_cv._texcoords, bind, index);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::copy_arc_pointers
|
||||
// Access: Public
|
||||
// Description: Creates _net_transform_arcs and _local_transform_arcs
|
||||
// as appropriate in each of the qpCharacter's joints, as
|
||||
// copied from the other qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCharacter::
|
||||
copy_arc_pointers(const qpCharacter *from, const qpCharacter::ArcMap &arc_map) {
|
||||
nassertv(_parts.size() == from->_parts.size());
|
||||
for (int i = 0; i < (int)_parts.size(); i++) {
|
||||
if (_parts[i]->is_of_type(CharacterJoint::get_class_type())) {
|
||||
nassertv(_parts[i] != from->_parts[i]);
|
||||
CharacterJoint *source_joint;
|
||||
CharacterJoint *dest_joint;
|
||||
DCAST_INTO_V(source_joint, from->_parts[i]);
|
||||
DCAST_INTO_V(dest_joint, _parts[i]);
|
||||
|
||||
CharacterJoint::ArcList::const_iterator ai;
|
||||
for (ai = source_joint->_net_transform_arcs.begin();
|
||||
ai != source_joint->_net_transform_arcs.end();
|
||||
++ai) {
|
||||
NodeRelation *source_arc = (*ai);
|
||||
|
||||
ArcMap::const_iterator mi;
|
||||
mi = arc_map.find(source_arc);
|
||||
if (mi != arc_map.end()) {
|
||||
NodeRelation *dest_arc = (*mi).second;
|
||||
|
||||
// Here's an internal joint that the source qpCharacter was
|
||||
// animating directly. We'll animate our corresponding
|
||||
// joint the same way.
|
||||
dest_joint->add_net_transform(dest_arc);
|
||||
}
|
||||
}
|
||||
|
||||
for (ai = source_joint->_local_transform_arcs.begin();
|
||||
ai != source_joint->_local_transform_arcs.end();
|
||||
++ai) {
|
||||
NodeRelation *source_arc = (*ai);
|
||||
|
||||
ArcMap::const_iterator mi;
|
||||
mi = arc_map.find(source_arc);
|
||||
if (mi != arc_map.end()) {
|
||||
NodeRelation *dest_arc = (*mi).second;
|
||||
|
||||
// Here's an internal joint that the source qpCharacter was
|
||||
// animating directly. We'll animate our corresponding
|
||||
// joint the same way.
|
||||
dest_joint->add_local_transform(dest_arc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCharacter::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCharacter::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
qpPartBundleNode::write_datagram(manager, dg);
|
||||
_cv.write_datagram(manager, dg);
|
||||
manager->write_pointer(dg, _computed_vertices);
|
||||
|
||||
dg.add_uint16(_parts.size());
|
||||
Parts::const_iterator pi;
|
||||
for (pi = _parts.begin(); pi != _parts.end(); pi++) {
|
||||
manager->write_pointer(dg, (*pi));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::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 qpCharacter::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = qpPartBundleNode::complete_pointers(p_list, manager);
|
||||
_computed_vertices = DCAST(ComputedVertices, p_list[pi++]);
|
||||
|
||||
int num_parts = _parts.size();
|
||||
for (int i = 0; i < num_parts; i++) {
|
||||
_parts[i] = DCAST(PartGroup, p_list[pi++]);
|
||||
}
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type qpCharacter is encountered
|
||||
// in the Bam file. It should create the qpCharacter
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *qpCharacter::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
qpCharacter *node = new qpCharacter("");
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCharacter::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 qpCharacter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCharacter::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
qpPartBundleNode::fillin(scan, manager);
|
||||
_cv.fillin(scan, manager);
|
||||
manager->read_pointer(scan, this);
|
||||
|
||||
// Read the number of parts to expect in the _parts list, and then
|
||||
// fill the array up with NULLs. We'll fill in the actual values in
|
||||
// complete_pointers, later.
|
||||
int num_parts = scan.get_uint16();
|
||||
_parts.clear();
|
||||
_parts.reserve(num_parts);
|
||||
for (int i = 0; i < num_parts; i++) {
|
||||
manager->read_pointer(scan, this);
|
||||
_parts.push_back((PartGroup *)NULL);
|
||||
}
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
// Reinitialize our collector with our name, now that we know it.
|
||||
if (has_name()) {
|
||||
_char_pcollector =
|
||||
PStatCollector(_anim_pcollector, get_name());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
// Filename: qpcharacter.h
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef qpCHARACTER_H
|
||||
#define qpCHARACTER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "computedVertices.h"
|
||||
|
||||
#include "qppartBundleNode.h"
|
||||
#include "vector_PartGroupStar.h"
|
||||
#include "pointerTo.h"
|
||||
#include "geom.h"
|
||||
#include "pStatCollector.h"
|
||||
|
||||
class CharacterJointBundle;
|
||||
class ComputedVertices;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpCharacter
|
||||
// Description : An animated character, with skeleton-morph animation
|
||||
// and either soft-skinned or hard-skinned vertices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA qpCharacter : public qpPartBundleNode {
|
||||
protected:
|
||||
qpCharacter(const qpCharacter ©);
|
||||
|
||||
public:
|
||||
qpCharacter(const string &name);
|
||||
virtual ~qpCharacter();
|
||||
|
||||
virtual PandaNode *make_copy() const;
|
||||
|
||||
virtual bool safe_to_transform() const;
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverserData &data);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE CharacterJointBundle *get_bundle() const;
|
||||
|
||||
INLINE ComputedVertices *get_computed_vertices() const;
|
||||
INLINE int get_num_parts() const;
|
||||
INLINE PartGroup *get_part(int n) const;
|
||||
|
||||
INLINE void write_parts(ostream &out) const;
|
||||
INLINE void write_part_values(ostream &out) const;
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
void copy_joints(PartGroup *copy, PartGroup *orig);
|
||||
|
||||
/*
|
||||
typedef pmap<NodeRelation *, NodeRelation *> ArcMap;
|
||||
virtual Node *r_copy_subgraph(TypeHandle graph_type,
|
||||
InstanceMap &inst_map) const;
|
||||
void r_copy_char(Node *dest, const Node *source, TypeHandle graph_type,
|
||||
const qpCharacter *from, ArcMap &arc_map);
|
||||
PT(Geom) copy_geom(Geom *source, const qpCharacter *from);
|
||||
void copy_arc_pointers(const qpCharacter *from, const ArcMap &arc_map);
|
||||
*/
|
||||
|
||||
// These are the actual dynamic vertex pools for this qpCharacter's
|
||||
// ComputedVertices--the vertices that it will recompute each frame
|
||||
// based on the soft-skinning and morphing requirements. Note that
|
||||
// we store this concretely, instead of as a pointer, just because
|
||||
// we don't really need to make it a pointer.
|
||||
DynamicVertices _cv;
|
||||
|
||||
// And this is the object that animates them. It *is* a pointer, so
|
||||
// it can be shared between multiple instances of this qpCharacter.
|
||||
PT(ComputedVertices) _computed_vertices;
|
||||
|
||||
// This vector is used by the ComputedVertices object to index back
|
||||
// into our joints and sliders.
|
||||
typedef vector_PartGroupStar Parts;
|
||||
Parts _parts;
|
||||
|
||||
// Statistics
|
||||
PStatCollector _char_pcollector;
|
||||
static PStatCollector _anim_pcollector;
|
||||
|
||||
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:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
qpPartBundleNode::init_type();
|
||||
register_type(_type_handle, "qpCharacter",
|
||||
qpPartBundleNode::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class qpCharacterMaker;
|
||||
friend class ComputedVerticesMaker;
|
||||
friend class ComputedVertices;
|
||||
};
|
||||
|
||||
#include "qpcharacter.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -9,12 +9,22 @@
|
|||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
||||
#define SOURCES \
|
||||
animBundleMaker.h \
|
||||
characterMaker.h \
|
||||
qpcharacterMaker.h \
|
||||
computedVerticesMaker.I computedVerticesMaker.h \
|
||||
computedVerticesMakerEntity.I computedVerticesMakerEntity.h \
|
||||
config_egg2pg.h \
|
||||
eggBinner.h \
|
||||
eggLoaderBase.h \
|
||||
qpeggLoader.h \
|
||||
qpload_egg_file.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
animBundleMaker.cxx \
|
||||
characterMaker.cxx \
|
||||
qpcharacterMaker.cxx \
|
||||
computedVerticesMaker.cxx \
|
||||
config_egg2pg.cxx \
|
||||
eggBinner.cxx \
|
||||
qpeggLoader.cxx \
|
||||
|
|
@ -27,9 +37,6 @@
|
|||
#endif
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_egg2pg.h \
|
||||
eggBinner.h \
|
||||
qpeggLoader.h \
|
||||
qpload_egg_file.h
|
||||
qpload_egg_file.h config_egg2pg.h
|
||||
|
||||
#end lib_target
|
||||
|
|
|
|||
|
|
@ -17,18 +17,19 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "animBundleMaker.h"
|
||||
#include "config_egg2sg.h"
|
||||
#include "config_egg2pg.h"
|
||||
|
||||
#include <eggTable.h>
|
||||
#include <eggAnimData.h>
|
||||
#include <eggSAnimData.h>
|
||||
#include <eggXfmAnimData.h>
|
||||
#include <eggXfmSAnim.h>
|
||||
#include <eggGroupNode.h>
|
||||
#include <animBundle.h>
|
||||
#include <animBundleNode.h>
|
||||
#include <animChannelMatrixXfmTable.h>
|
||||
#include <animChannelScalarTable.h>
|
||||
#include "eggTable.h"
|
||||
#include "eggAnimData.h"
|
||||
#include "eggSAnimData.h"
|
||||
#include "eggXfmAnimData.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
#include "eggGroupNode.h"
|
||||
#include "animBundle.h"
|
||||
#include "animBundleNode.h"
|
||||
#include "qpanimBundleNode.h"
|
||||
#include "animChannelMatrixXfmTable.h"
|
||||
#include "animChannelScalarTable.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnimBundleMaker::Construtor
|
||||
|
|
@ -46,18 +47,18 @@ AnimBundleMaker(EggTable *root) : _root(root) {
|
|||
inspect_tree(root);
|
||||
|
||||
if (!_ok_fps) {
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "AnimBundle " << _root->get_name()
|
||||
<< " specifies contradictory frame rates.\n";
|
||||
} else if (_fps == 0.0f) {
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "AnimBundle " << _root->get_name()
|
||||
<< " does not specify a frame rate.\n";
|
||||
_fps = 24.0f;
|
||||
}
|
||||
|
||||
if (!_ok_num_frames) {
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "AnimBundle " << _root->get_name()
|
||||
<< " specifies contradictory number of frames.\n";
|
||||
}
|
||||
|
|
@ -74,6 +75,16 @@ make_node() {
|
|||
return new AnimBundleNode(make_bundle());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnimBundleMaker::make_qpnode
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpAnimBundleNode *AnimBundleMaker::
|
||||
make_qpnode() {
|
||||
return new qpAnimBundleNode("", make_bundle());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnimBundleMaker::make_bundle
|
||||
// Access: Private
|
||||
|
|
@ -196,7 +207,7 @@ build_hierarchy(EggTable *egg_table, AnimGroup *parent) {
|
|||
if (this_node == NULL) {
|
||||
this_node = create_xfm_channel((*ci), egg_table->get_name(), parent);
|
||||
} else {
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "Duplicate xform table under node "
|
||||
<< egg_table->get_name() << "\n";
|
||||
}
|
||||
|
|
@ -271,7 +282,7 @@ create_xfm_channel(EggNode *egg_node, const string &name,
|
|||
return create_xfm_channel(egg_anim, name, parent);
|
||||
}
|
||||
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "Inappropriate node named xform under node "
|
||||
<< name << "\n";
|
||||
return NULL;
|
||||
|
|
@ -304,7 +315,7 @@ create_xfm_channel(EggXfmSAnim *egg_anim, const string &name,
|
|||
EggSAnimData *child = DCAST(EggSAnimData, *ci);
|
||||
|
||||
if (child->get_name().empty()) {
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "Unnamed subtable of <Xfm$Anim_S$> " << name
|
||||
<< "\n";
|
||||
} else {
|
||||
|
|
@ -312,12 +323,12 @@ create_xfm_channel(EggXfmSAnim *egg_anim, const string &name,
|
|||
|
||||
if (child->get_name().length() > 1 ||
|
||||
!table->is_valid_id(table_id)) {
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "Unexpected table name " << child->get_name()
|
||||
<< ", child of " << name << "\n";
|
||||
|
||||
} else if (table->has_table(table_id)) {
|
||||
egg2sg_cat.warning()
|
||||
egg2pg_cat.warning()
|
||||
<< "Duplicate table definition for " << table_id
|
||||
<< " under " << name << "\n";
|
||||
|
||||
|
|
@ -19,11 +19,8 @@
|
|||
#ifndef ANIMBUNDLEMAKER_H
|
||||
#define ANIMBUNDLEMAKER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <typedef.h>
|
||||
|
||||
#include <string>
|
||||
#include "pandabase.h"
|
||||
#include "typedef.h"
|
||||
|
||||
class EggNode;
|
||||
class EggGroupNode;
|
||||
|
|
@ -33,6 +30,7 @@ class EggSAnimData;
|
|||
class AnimGroup;
|
||||
class AnimBundle;
|
||||
class AnimBundleNode;
|
||||
class qpAnimBundleNode;
|
||||
class AnimChannelScalarTable;
|
||||
class AnimChannelMatrixXfmTable;
|
||||
|
||||
|
|
@ -46,6 +44,7 @@ public:
|
|||
AnimBundleMaker(EggTable *root);
|
||||
|
||||
AnimBundleNode *make_node();
|
||||
qpAnimBundleNode *make_qpnode();
|
||||
|
||||
private:
|
||||
AnimBundle *make_bundle();
|
||||
|
|
@ -17,19 +17,19 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "characterMaker.h"
|
||||
#include "eggLoader.h"
|
||||
#include "config_egg2sg.h"
|
||||
#include "qpeggLoader.h"
|
||||
#include "config_egg2pg.h"
|
||||
|
||||
#include <computedVertices.h>
|
||||
#include <eggGroup.h>
|
||||
#include <eggPrimitive.h>
|
||||
#include <partGroup.h>
|
||||
#include <characterJoint.h>
|
||||
#include <characterJointBundle.h>
|
||||
#include <characterSlider.h>
|
||||
#include <character.h>
|
||||
#include <renderRelation.h>
|
||||
#include <transformTransition.h>
|
||||
#include "computedVertices.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "partGroup.h"
|
||||
#include "characterJoint.h"
|
||||
#include "characterJointBundle.h"
|
||||
#include "characterSlider.h"
|
||||
#include "character.h"
|
||||
#include "renderRelation.h"
|
||||
#include "transformTransition.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::Construtor
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CharacterMaker::
|
||||
CharacterMaker(EggGroup *root, EggLoader &loader)
|
||||
CharacterMaker(EggGroup *root, EggLoaderBase &loader)
|
||||
: _loader(loader), _egg_root(root) {
|
||||
|
||||
_character_node = new Character(_egg_root->get_name());
|
||||
|
|
@ -19,14 +19,12 @@
|
|||
#ifndef CHARACTERMAKER_H
|
||||
#define CHARACTERMAKER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "computedVerticesMaker.h"
|
||||
|
||||
#include <vector_PartGroupStar.h>
|
||||
#include <typedef.h>
|
||||
|
||||
#include <string>
|
||||
#include "vector_PartGroupStar.h"
|
||||
#include "typedef.h"
|
||||
#include "pmap.h"
|
||||
|
||||
class EggNode;
|
||||
|
|
@ -39,7 +37,7 @@ class Character;
|
|||
class CharacterSlider;
|
||||
class MovingPartBase;
|
||||
class NamedNode;
|
||||
class EggLoader;
|
||||
class EggLoaderBase;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : CharacterMaker
|
||||
|
|
@ -49,7 +47,7 @@ class EggLoader;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG CharacterMaker {
|
||||
public:
|
||||
CharacterMaker(EggGroup *root, EggLoader &loader);
|
||||
CharacterMaker(EggGroup *root, EggLoaderBase &loader);
|
||||
|
||||
Character *make_node();
|
||||
|
||||
|
|
@ -78,7 +76,7 @@ private:
|
|||
typedef vector_PartGroupStar Parts;
|
||||
Parts _parts;
|
||||
|
||||
EggLoader &_loader;
|
||||
EggLoaderBase &_loader;
|
||||
EggGroup *_egg_root;
|
||||
Character *_character_node;
|
||||
CharacterJointBundle *_bundle;
|
||||
|
|
@ -19,12 +19,12 @@
|
|||
#include "computedVerticesMaker.h"
|
||||
#include "characterMaker.h"
|
||||
|
||||
#include <characterJoint.h>
|
||||
#include <character.h>
|
||||
#include <computedVertices.h>
|
||||
#include <eggNode.h>
|
||||
#include <eggGroup.h>
|
||||
#include <eggVertex.h>
|
||||
#include "characterJoint.h"
|
||||
#include "character.h"
|
||||
#include "computedVertices.h"
|
||||
#include "eggNode.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggVertex.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -447,6 +447,141 @@ make_computed_vertices(Character *character, CharacterMaker &char_maker) {
|
|||
return comp_verts;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ComputedVerticesMaker::make_computed_vertices
|
||||
// Access: Public
|
||||
// Description: After all spaces have been defined and all vertices
|
||||
// added, creates a new ComputedVertices object and
|
||||
// returns it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ComputedVertices *ComputedVerticesMaker::
|
||||
make_computed_vertices(qpCharacter *character, qpCharacterMaker &char_maker) {
|
||||
// We must first build up a set of all the unique kinds of vertex
|
||||
// transforms.
|
||||
typedef pset<ComputedVertices::VertexTransform> VertexTransforms;
|
||||
VertexTransforms transforms;
|
||||
|
||||
TransformSpaces::const_iterator tsi;
|
||||
for (tsi = _transforms.begin();
|
||||
tsi != _transforms.end();
|
||||
++tsi) {
|
||||
const JointWeights &jw = (*tsi).first;
|
||||
const VertexCollection &vc = (*tsi).second;
|
||||
|
||||
JointWeights::const_iterator jwi;
|
||||
for (jwi = jw.begin(); jwi != jw.end(); ++jwi) {
|
||||
double weight = (*jwi).second;
|
||||
EggNode *egg_joint = (*jwi).first;
|
||||
int joint_index = char_maker.egg_to_index(egg_joint);
|
||||
|
||||
// Look for a VertexTransform that matches this template.
|
||||
ComputedVertices::VertexTransform new_vt;
|
||||
new_vt._joint_index = joint_index;
|
||||
new_vt._effect = (float)weight;
|
||||
|
||||
// This will either insert the VertexTransform into the set and
|
||||
// return its newly-created iterator, or it will return the
|
||||
// iterator referring to the previously-inserted VertexTransform
|
||||
// like this.
|
||||
VertexTransforms::iterator vti = transforms.insert(new_vt).first;
|
||||
|
||||
// We can discard the const-ness of the set's iterator, because
|
||||
// we will only be changing a part of the VertexTransform that
|
||||
// doesn't affect its sort order within the set.
|
||||
ComputedVertices::VertexTransform &insert_vt =
|
||||
(ComputedVertices::VertexTransform &)*vti;
|
||||
|
||||
// Now add in all the vertices and normals.
|
||||
copy(vc._vindex.begin(), vc._vindex.end(),
|
||||
back_inserter(insert_vt._vindex));
|
||||
copy(vc._nindex.begin(), vc._nindex.end(),
|
||||
back_inserter(insert_vt._nindex));
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, now we have the set of all VertexTransforms. Create a
|
||||
// ComputedVertices object that reflects this.
|
||||
ComputedVertices *comp_verts = new ComputedVertices;
|
||||
copy(transforms.begin(), transforms.end(),
|
||||
back_inserter(comp_verts->_transforms));
|
||||
|
||||
character->_cv._coords = _coords;
|
||||
character->_cv._norms = _norms;
|
||||
character->_cv._colors = _colors;
|
||||
character->_cv._texcoords = _texcoords;
|
||||
|
||||
// Finally, add in all the morph definitions.
|
||||
Morphs::const_iterator mi;
|
||||
for (mi = _morphs.begin(); mi != _morphs.end(); ++mi) {
|
||||
const string &name = (*mi).first;
|
||||
const MorphList &mlist = (*mi).second;
|
||||
|
||||
int slider_index = char_maker.create_slider(name);
|
||||
|
||||
if (!mlist._vmorphs.empty()) {
|
||||
// We push an empty MorphVertex object and then modify it,
|
||||
// rather than filling it first and then pushing it, just to
|
||||
// avoid unnecessary copying of data.
|
||||
comp_verts->_vertex_morphs.push_back(ComputedVerticesMorphVertex());
|
||||
ComputedVerticesMorphVertex &mv = comp_verts->_vertex_morphs.back();
|
||||
mv._slider_index = slider_index;
|
||||
|
||||
VertexMorphList::const_iterator vmi;
|
||||
for (vmi = mlist._vmorphs.begin();
|
||||
vmi != mlist._vmorphs.end();
|
||||
++vmi) {
|
||||
mv._morphs.push_back(ComputedVerticesMorphValue3((*vmi).first,
|
||||
(*vmi).second));
|
||||
}
|
||||
}
|
||||
|
||||
if (!mlist._nmorphs.empty()) {
|
||||
comp_verts->_normal_morphs.push_back(ComputedVerticesMorphNormal());
|
||||
ComputedVerticesMorphNormal &mv = comp_verts->_normal_morphs.back();
|
||||
mv._slider_index = slider_index;
|
||||
|
||||
NormalMorphList::const_iterator vmi;
|
||||
for (vmi = mlist._nmorphs.begin();
|
||||
vmi != mlist._nmorphs.end();
|
||||
++vmi) {
|
||||
mv._morphs.push_back(ComputedVerticesMorphValue3((*vmi).first,
|
||||
(*vmi).second));
|
||||
}
|
||||
}
|
||||
|
||||
if (!mlist._tmorphs.empty()) {
|
||||
comp_verts->_texcoord_morphs.push_back(ComputedVerticesMorphTexCoord());
|
||||
ComputedVerticesMorphTexCoord &mv = comp_verts->_texcoord_morphs.back();
|
||||
mv._slider_index = slider_index;
|
||||
|
||||
TexCoordMorphList::const_iterator vmi;
|
||||
for (vmi = mlist._tmorphs.begin();
|
||||
vmi != mlist._tmorphs.end();
|
||||
++vmi) {
|
||||
mv._morphs.push_back(ComputedVerticesMorphValue2((*vmi).first,
|
||||
(*vmi).second));
|
||||
}
|
||||
}
|
||||
|
||||
if (!mlist._cmorphs.empty()) {
|
||||
comp_verts->_color_morphs.push_back(ComputedVerticesMorphColor());
|
||||
ComputedVerticesMorphColor &mv = comp_verts->_color_morphs.back();
|
||||
mv._slider_index = slider_index;
|
||||
|
||||
ColorMorphList::const_iterator vmi;
|
||||
for (vmi = mlist._cmorphs.begin();
|
||||
vmi != mlist._cmorphs.end();
|
||||
++vmi) {
|
||||
mv._morphs.push_back(ComputedVerticesMorphValue4((*vmi).first,
|
||||
(*vmi).second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
comp_verts->make_orig(character);
|
||||
return comp_verts;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ComputedVerticesMaker::write
|
||||
|
|
@ -19,25 +19,26 @@
|
|||
#ifndef COMPUTEDVERTICESMAKER_H
|
||||
#define COMPUTEDVERTICESMAKER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "computedVerticesMakerEntity.h"
|
||||
|
||||
#include <computedVerticesMorph.h>
|
||||
#include <pointerToArray.h>
|
||||
#include <luse.h>
|
||||
#include <typedef.h>
|
||||
#include <eggMorphList.h>
|
||||
#include <pta_Vertexf.h>
|
||||
#include <pta_Normalf.h>
|
||||
#include <pta_Colorf.h>
|
||||
#include <pta_TexCoordf.h>
|
||||
#include "computedVerticesMorph.h"
|
||||
#include "pointerToArray.h"
|
||||
#include "luse.h"
|
||||
#include "typedef.h"
|
||||
#include "eggMorphList.h"
|
||||
#include "pta_Vertexf.h"
|
||||
#include "pta_Normalf.h"
|
||||
#include "pta_Colorf.h"
|
||||
#include "pta_TexCoordf.h"
|
||||
|
||||
#include "pset.h"
|
||||
#include "pmap.h"
|
||||
|
||||
class ComputedVertices;
|
||||
class CharacterMaker;
|
||||
class qpCharacterMaker;
|
||||
class EggNode;
|
||||
class EggVertex;
|
||||
|
||||
|
|
@ -81,6 +82,9 @@ public:
|
|||
ComputedVertices *make_computed_vertices(Character *character,
|
||||
CharacterMaker &char_maker);
|
||||
|
||||
ComputedVertices *make_computed_vertices(qpCharacter *character,
|
||||
qpCharacterMaker &char_maker);
|
||||
|
||||
void write(ostream &out) const;
|
||||
|
||||
public:
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <math.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ComputedVerticesMakerEntity::Constructor
|
||||
|
|
@ -19,14 +19,15 @@
|
|||
#ifndef COMPUTEDVERTICESMAKERENTITY_H
|
||||
#define COMPUTEDVERTICESMAKERENTITY_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include <luse.h>
|
||||
#include <eggMorphList.h>
|
||||
#include <typedef.h>
|
||||
#include <pointerToArray.h>
|
||||
#include "luse.h"
|
||||
#include "eggMorphList.h"
|
||||
#include "typedef.h"
|
||||
#include "pointerToArray.h"
|
||||
|
||||
#include "pmap.h"
|
||||
#include <math.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : ComputedVerticesMakerEntity
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
#include "config_egg2pg.cxx"
|
||||
#include "eggBinner.cxx"
|
||||
#include "animBundleMaker.cxx"
|
||||
#include "characterMaker.cxx"
|
||||
#include "qpcharacterMaker.cxx"
|
||||
#include "computedVerticesMaker.cxx"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include "config_egg2pg.cxx"
|
||||
#include "eggBinner.cxx"
|
||||
#include "qpeggLoader.cxx"
|
||||
#include "qpload_egg_file.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "qpeggLoader.h"
|
||||
#include "config_egg2pg.h"
|
||||
#include "nodeChain.h"
|
||||
#include "renderState.h"
|
||||
#include "transformState.h"
|
||||
#include "textureAttrib.h"
|
||||
|
|
@ -48,7 +49,10 @@
|
|||
#include "eggBin.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggBinner.h"
|
||||
#include "nodeChain.h"
|
||||
#include "qpcharacterMaker.h"
|
||||
#include "qpcharacter.h"
|
||||
#include "animBundleMaker.h"
|
||||
#include "qpanimBundleNode.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <algorithm>
|
||||
|
|
@ -283,7 +287,6 @@ void qpEggLoader::
|
|||
make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent,
|
||||
const LMatrix4d *transform,
|
||||
ComputedVerticesMaker &_comp_verts_maker) {
|
||||
/*
|
||||
BuilderBucket bucket;
|
||||
setup_bucket(bucket, parent, egg_prim);
|
||||
|
||||
|
|
@ -396,7 +399,6 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent,
|
|||
}
|
||||
|
||||
_builder.add_prim(bucket, bprim);
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1338,11 +1340,9 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
|
|||
}
|
||||
|
||||
if (egg_group->get_dart_type() != EggGroup::DT_none) {
|
||||
/*
|
||||
// A group with the <Dart> flag set means to create a character.
|
||||
CharacterMaker char_maker(egg_group, *this);
|
||||
qpCharacterMaker char_maker(egg_group, *this);
|
||||
node = char_maker.make_node();
|
||||
*/
|
||||
|
||||
} else if (egg_group->get_cs_type() != EggGroup::CST_none &&
|
||||
egg_group->get_cs_type() != EggGroup::CST_geode) {
|
||||
|
|
@ -1493,8 +1493,6 @@ create_group_arc(EggGroup *egg_group, PandaNode *parent, PandaNode *node) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode *qpEggLoader::
|
||||
make_node(EggTable *egg_table, PandaNode *parent) {
|
||||
return (PandaNode *)NULL;
|
||||
/*
|
||||
if (egg_table->get_table_type() != EggTable::TT_bundle) {
|
||||
// We only do anything with bundles. Isolated tables are treated
|
||||
// as ordinary groups.
|
||||
|
|
@ -1504,9 +1502,9 @@ make_node(EggTable *egg_table, PandaNode *parent) {
|
|||
// It's an actual bundle, so make an AnimBundle from it and its
|
||||
// descendants.
|
||||
AnimBundleMaker bundle_maker(egg_table);
|
||||
AnimBundleNode *node = bundle_maker.make_node();
|
||||
return new PandaNode(parent, node);
|
||||
*/
|
||||
qpAnimBundleNode *node = bundle_maker.make_qpnode();
|
||||
parent->add_child(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include "indirectCompareTo.h"
|
||||
#include "textureAttrib.h"
|
||||
|
||||
#include "eggLoaderBase.h"
|
||||
|
||||
class EggNode;
|
||||
class EggBin;
|
||||
class EggTable;
|
||||
|
|
@ -57,7 +59,7 @@ class CollisionPolygon;
|
|||
//
|
||||
// This class isn't exported from this package.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class qpEggLoader {
|
||||
class qpEggLoader : public EggLoaderBase {
|
||||
public:
|
||||
qpEggLoader();
|
||||
qpEggLoader(const EggData &data);
|
||||
|
|
|
|||
|
|
@ -11,13 +11,11 @@
|
|||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
||||
#define SOURCES \
|
||||
animBundleMaker.h characterMaker.h computedVerticesMaker.I \
|
||||
computedVerticesMaker.h config_egg2sg.h \
|
||||
config_egg2sg.h \
|
||||
deferredArcProperty.h deferredArcTraverser.h \
|
||||
eggLoader.h load_egg_file.h loaderFileTypeEgg.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
animBundleMaker.cxx characterMaker.cxx computedVerticesMaker.cxx \
|
||||
config_egg2sg.cxx deferredArcProperty.cxx \
|
||||
deferredArcTraverser.cxx eggLoader.cxx \
|
||||
load_egg_file.cxx loaderFileTypeEgg.cxx
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
|
||||
#include "animBundleMaker.cxx"
|
||||
#include "characterMaker.cxx"
|
||||
#include "computedVerticesMaker.cxx"
|
||||
#include "deferredArcProperty.cxx"
|
||||
#include "deferredArcTraverser.cxx"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <pandabase.h>
|
||||
|
||||
#include "deferredArcTraverser.h"
|
||||
#include "eggLoaderBase.h"
|
||||
|
||||
#include <eggData.h>
|
||||
#include <eggTexture.h>
|
||||
|
|
@ -62,7 +63,7 @@ class CollisionPolygon;
|
|||
//
|
||||
// This class isn't exported from this package.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EggLoader {
|
||||
class EggLoader : public EggLoaderBase {
|
||||
public:
|
||||
EggLoader();
|
||||
EggLoader(const EggData &data);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "texturePool.h"
|
||||
#include "dSearchPath.h"
|
||||
#include "loader.h"
|
||||
#include "auto_bind.h"
|
||||
|
||||
// These are in support of legacy data graph operations.
|
||||
#include "namedNode.h"
|
||||
|
|
@ -294,6 +295,14 @@ main(int argc, char *argv[]) {
|
|||
// Put something in the scene graph to look at.
|
||||
get_models(render, argc, argv);
|
||||
|
||||
// If we happened to load up both a character file and its matching
|
||||
// animation file, attempt to bind them together now and start the
|
||||
// animations looping.
|
||||
AnimControlCollection anim_controls;
|
||||
auto_bind(render, anim_controls, ~0);
|
||||
anim_controls.loop_all(true);
|
||||
|
||||
|
||||
// Tick the clock once so we won't count the time spent loading up
|
||||
// files, above, in our frame rate average.
|
||||
ClockObject::get_global_clock()->tick();
|
||||
|
|
|
|||
Loading…
Reference in New Issue