15 #include "character.h"
16 #include "characterJoint.h"
17 #include "config_char.h"
21 #include "datagramIterator.h"
22 #include "bamReader.h"
23 #include "bamWriter.h"
24 #include "pStatTimer.h"
25 #include "animControl.h"
26 #include "clockObject.h"
27 #include "pStatTimer.h"
29 #include "cullTraverser.h"
30 #include "cullTraverserData.h"
42 Character(
const Character ©,
bool copy_bundles) :
44 _lod_center(copy._lod_center),
45 _lod_far_distance(copy._lod_far_distance),
46 _lod_near_distance(copy._lod_near_distance),
47 _lod_delay_factor(copy._lod_delay_factor),
48 _do_lod_animation(copy._do_lod_animation),
49 _joints_pcollector(copy._joints_pcollector),
50 _skinning_pcollector(copy._skinning_pcollector)
56 int num_bundles = copy.get_num_bundles();
57 for (
int i = 0; i < num_bundles; ++i) {
60 add_bundle(new_bundle);
64 int num_bundles = copy.get_num_bundles();
65 for (
int i = 0; i < num_bundles; ++i) {
66 PartBundle *orig_bundle = copy.get_bundle(i);
67 add_bundle(orig_bundle);
70 _last_auto_update = -1.0;
72 _view_distance2 = 0.0f;
81 Character(
const string &name) :
83 _joints_pcollector(
PStatCollector(_animation_pcollector, name),
"Joints"),
84 _skinning_pcollector(
PStatCollector(_animation_pcollector, name),
"Vertices")
87 clear_lod_animation();
88 _last_auto_update = -1.0;
90 _view_distance2 = 0.0f;
100 int num_bundles = get_num_bundles();
101 for (
int i = 0; i < num_bundles; ++i) {
102 r_clear_joint_characters(get_bundle(i));
158 steal_bundles(c_other);
198 if (_do_lod_animation) {
201 CPT(TransformState) rel_transform = get_rel_transform(trav, data);
202 LPoint3 center = _lod_center * rel_transform->get_mat();
203 PN_stdfloat dist2 = center.dot(center);
205 if (this_frame != _view_frame || dist2 < _view_distance2) {
206 _view_frame = this_frame;
207 _view_distance2 = dist2;
210 PN_stdfloat dist = sqrt(dist2);
212 if (dist > _lod_near_distance) {
213 delay = _lod_delay_factor * (dist - _lod_near_distance) / (_lod_far_distance - _lod_near_distance);
214 nassertr(delay > 0.0,
false);
216 set_lod_current_delay(delay);
218 if (char_cat.is_spam()) {
221 << this_frame <<
" is " << dist <<
", computed delay is " << delay
252 calc_tight_bounds(
LPoint3 &min_point,
LPoint3 &max_point,
bool &found_any,
253 const TransformState *transform,
Thread *current_thread)
const {
264 Parents parents = get_parents();
265 for (
int i = 0; i < parents.get_num_parents(); ++i) {
267 parent->get_bounds();
270 return PandaNode::calc_tight_bounds(min_point, max_point,
271 found_any, transform, current_thread);
289 if (old_bundle == new_bundle) {
296 Bundles::const_iterator bi;
297 for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
298 if ((*bi)->get_bundle() == old_bundle) {
299 old_bundle_handle = (*bi);
303 nassertv(!old_bundle_handle.is_null());
339 PartBundle *old_bundle = old_bundle_handle->
get_bundle();
340 PartBundle *new_bundle = new_bundle_handle->
get_bundle();
343 update_bundle(old_bundle_handle, new_bundle);
379 PN_stdfloat far_distance, PN_stdfloat near_distance,
380 PN_stdfloat delay_factor) {
381 nassertv(far_distance >= near_distance);
382 nassertv(delay_factor >= 0.0f);
383 _lod_center = center;
384 _lod_far_distance = far_distance;
385 _lod_near_distance = near_distance;
386 _lod_delay_factor = delay_factor;
387 _do_lod_animation = (_lod_far_distance > _lod_near_distance && _lod_delay_factor > 0.0);
388 if (!_do_lod_animation) {
389 set_lod_current_delay(0.0);
404 _lod_far_distance = 0.0f;
405 _lod_near_distance = 0.0f;
406 _lod_delay_factor = 0.0f;
407 _do_lod_animation =
false;
408 set_lod_current_delay(0.0);
420 int num_bundles = get_num_bundles();
421 for (
int i = 0; i < num_bundles; ++i) {
424 part->
is_of_type(CharacterJoint::get_class_type())) {
441 int num_bundles = get_num_bundles();
442 for (
int i = 0; i < num_bundles; ++i) {
445 part->
is_of_type(CharacterSlider::get_class_type())) {
462 int num_bundles = get_num_bundles();
463 for (
int i = 0; i < num_bundles; ++i) {
464 get_bundle(i)->
write(out, 0);
477 int num_bundles = get_num_bundles();
478 for (
int i = 0; i < num_bundles; ++i) {
510 if (now != _last_auto_update) {
511 _last_auto_update = now;
513 if (char_cat.is_spam()) {
516 <<
" at time " << now <<
"\n";
536 int num_bundles = get_num_bundles();
537 for (
int i = 0; i < num_bundles; ++i) {
568 DCAST_INTO_V(from_char, from);
572 int num_bundles = get_num_bundles();
573 nassertv(from_char->get_num_bundles() == num_bundles);
575 for (i = 0; i < num_bundles; ++i) {
576 fill_joint_map(joint_map, get_bundle(i), from_char->get_bundle(i));
582 r_copy_char(
this, from_char, from_char, node_map, joint_map,
583 gvmap, gjmap, gsmap);
585 for (i = 0; i < num_bundles; ++i) {
586 copy_node_pointers(node_map, get_bundle(i), from_char->get_bundle(i));
598 update_bundle(
PartBundleHandle *old_bundle_handle, PartBundle *new_bundle) {
599 if (old_bundle_handle->
get_bundle() == new_bundle) {
607 r_merge_bundles(joint_map, old_bundle_handle->
get_bundle(), new_bundle);
609 PartBundleNode::update_bundle(old_bundle_handle, new_bundle);
615 r_update_geom(
this, joint_map, gvmap, gjmap, gsmap);
627 Camera *camera = trav->get_scene()->get_camera_node();
630 CPT(TransformState) rel_transform;
632 NodePath lod_center = camera->get_lod_center();
633 if (!lod_center.is_empty()) {
635 lod_center.get_net_transform()->invert_compose(data.get_net_transform(trav));
640 cull_center.get_net_transform()->invert_compose(data.get_net_transform(trav));
642 rel_transform = data.get_modelview_transform(trav);
646 return rel_transform;
658 if (even_animation) {
659 int num_bundles = get_num_bundles();
660 for (
int i = 0; i < num_bundles; ++i) {
664 int num_bundles = get_num_bundles();
665 for (
int i = 0; i < num_bundles; ++i) {
678 set_lod_current_delay(
double delay) {
679 int num_bundles = get_num_bundles();
680 for (
int i = 0; i < num_bundles; ++i) {
696 joint_map[orig] = copy;
702 while (i < copy_num_children && j < orig_num_children) {
706 if (pc->get_name() < ac->get_name()) {
708 }
else if (ac->get_name() < pc->get_name()) {
711 fill_joint_map(joint_map, pc, ac);
729 joint_map[old_group] = new_group;
731 if (new_group->
is_of_type(CharacterJoint::get_class_type())) {
733 DCAST_INTO_V(new_joint, new_group);
736 new_joint->_character =
this;
738 if (old_group != new_group &&
739 old_group->
is_of_type(CharacterJoint::get_class_type())) {
741 DCAST_INTO_V(old_joint, old_group);
745 old_joint->_character = NULL;
749 CharacterJoint::NodeList::iterator ni;
750 for (ni = old_joint->_net_transform_nodes.
begin();
751 ni != old_joint->_net_transform_nodes.
end();
753 new_joint->_net_transform_nodes.insert(*ni);
755 for (ni = old_joint->_local_transform_nodes.
begin();
756 ni != old_joint->_local_transform_nodes.
end();
758 new_joint->_local_transform_nodes.insert(*ni);
763 if (old_group == new_group) {
772 new_children.reserve(max(old_num_children, new_num_children));
774 while (i < old_num_children && j < new_num_children) {
778 if (pc->get_name() < ac->get_name()) {
782 new_children.push_back(new_pc);
784 r_merge_bundles(joint_map, pc, new_pc);
787 }
else if (ac->get_name() < pc->get_name()) {
790 new_children.push_back(ac);
792 r_merge_bundles(joint_map, ac, ac);
797 new_children.push_back(ac);
799 r_merge_bundles(joint_map, pc, ac);
805 while (i < old_num_children) {
811 new_children.push_back(new_pc);
813 r_merge_bundles(joint_map, pc, new_pc);
817 while (j < new_num_children) {
822 new_children.push_back(ac);
824 r_merge_bundles(joint_map, ac, ac);
828 new_group->_children.swap(new_children);
850 DCAST_INTO_V(source_gnode, source);
851 DCAST_INTO_V(dest_gnode, dest);
855 for (
int i = 0; i < num_geoms; i++) {
856 const Geom *geom = source_gnode->get_geom(i);
858 dest_gnode->
add_geom(copy_geom(geom, joint_map, gvmap, gjmap, gsmap), state);
863 for (
int i = 0; i < num_children; i++) {
873 dest_child = source_child->copy_subgraph();
881 r_copy_char(dest_child, source_child, from, node_map, joint_map,
882 gvmap, gjmap, gsmap);
884 dest->
add_child(dest_child, source_sort);
885 node_map[source_child] = dest_child;
903 DCAST_INTO_V(gnode, node);
906 for (
int i = 0; i < num_geoms; i++) {
907 CPT(
Geom) geom = gnode->get_geom(i);
908 PT(
Geom) new_geom = copy_geom(geom, joint_map, gvmap, gjmap, gsmap);
909 gnode->set_geom(i, new_geom);
914 for (
int i = 0; i < num_children; i++) {
917 r_update_geom(child, joint_map, gvmap, gjmap, gsmap);
930 copy_geom(const
Geom *source, const
Character::JointMap &joint_map,
933 CPT(GeomVertexFormat) format = source->get_vertex_data()->get_format();
934 if (format->get_animation().get_animation_type() ==
Geom::AT_none) {
936 return (
Geom *)source;
943 GeomVertexMap::iterator gvmi = gvmap.find(orig_vdata);
944 if (gvmi != gvmap.end()) {
945 new_vdata = (*gvmi).second;
949 new_vdata->set_transform_table(redirect_transform_table(orig_vdata->get_transform_table(), joint_map, gjmap));
950 new_vdata->set_transform_blend_table(redirect_transform_blend_table(orig_vdata->get_transform_blend_table(), joint_map, gjmap));
951 new_vdata->set_slider_table(redirect_slider_table(orig_vdata->get_slider_table(), gsmap));
953 gvmap.insert(GeomVertexMap::value_type(orig_vdata, new_vdata));
956 dest->set_vertex_data(new_vdata);
971 if (dest->
is_of_type(CharacterJoint::get_class_type())) {
972 nassertv(dest != source);
975 DCAST_INTO_V(source_joint, source);
976 DCAST_INTO_V(dest_joint, dest);
978 CharacterJoint::NodeList::const_iterator ai;
979 for (ai = source_joint->_net_transform_nodes.
begin();
980 ai != source_joint->_net_transform_nodes.
end();
984 NodeMap::const_iterator mi;
985 mi = node_map.find(source_node);
986 if (mi != node_map.end()) {
992 dest_joint->set_character(
this);
997 for (ai = source_joint->_local_transform_nodes.
begin();
998 ai != source_joint->_local_transform_nodes.
end();
1002 NodeMap::const_iterator mi;
1003 mi = node_map.find(source_node);
1004 if (mi != node_map.end()) {
1010 dest_joint->set_character(
this);
1021 while (i < dest_num_children && j < source_num_children) {
1025 if (pc->get_name() < ac->get_name()) {
1027 }
else if (ac->get_name() < pc->get_name()) {
1030 copy_node_pointers(node_map, pc, ac);
1054 int num_transforms = dest->get_num_transforms();
1055 for (
int i = 0; i < num_transforms; ++i) {
1059 dest->set_transform(i, new_jvt);
1063 return TransformTable::register_table(dest);
1083 int num_blends = dest->get_num_blends();
1084 for (
int i = 0; i < num_blends; ++i) {
1087 for (
int j = 0; j < num_transforms; ++j) {
1094 dest->set_blend(i, blend);
1116 int num_sliders = dest->get_num_sliders();
1117 for (
int i = 0; i < num_sliders; ++i) {
1121 dest->set_slider(i, new_cvs);
1125 return SliderTable::register_table(dest);
1140 GeomJointMap::iterator ji;
1141 ji = gjmap.find(vt);
1142 if (ji != gjmap.end()) {
1143 return (*ji).second;
1151 JointMap::const_iterator jmi = joint_map.find(orig_joint);
1152 if (jmi == joint_map.end()) {
1154 <<
"Could not find joint " << *orig_joint
1155 <<
" within the character hierarchy.\n";
1163 gjmap[vt] = new_jvt;
1177 GeomSliderMap::iterator ji;
1178 ji = gsmap.find(vs);
1179 if (ji != gsmap.end()) {
1180 return (*ji).second;
1193 gsmap[vs] = new_cvs;
1206 r_clear_joint_characters(
PartGroup *part) {
1207 if (part->
is_of_type(CharacterJoint::get_class_type())) {
1215 joint->set_character(NULL);
1220 for (
int i = 0; i < num_children; ++i) {
1222 r_clear_joint_characters(child);
1279 parse_params(params, scan, manager);
1280 node->fillin(scan, manager);
1294 PartBundleNode::fillin(scan, manager);
1300 for (
unsigned int i = 0; i < _temp_num_parts; i++) {
1307 _joints_pcollector =
1309 _skinning_pcollector =
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
A basic node of the scene graph or data graph.
This is our own Panda specialization on the default STL map.
void write_parts(ostream &out) const
Writes a list of the Character's joints and sliders, in their hierchical structure, to the indicated output stream.
virtual PandaNode * make_copy() const
The Character make_copy() function will make a new copy of the Character, with all of its joints copi...
The collection of all the joints and sliders in the character.
PandaNode * get_parent(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth parent node of this node.
virtual PartGroup * make_copy() const
Allocates and returns a new copy of the node.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void update()
Recalculates the Character's joints and vertices for the current frame.
virtual PandaNode * combine_with(PandaNode *other)
Collapses this PandaNode with the other PandaNode, if possible, and returns a pointer to the combined...
An animated character, with skeleton-morph animation and either soft-skinned or hard-skinned vertices...
virtual PandaNode * combine_with(PandaNode *other)
Collapses this node with the other node, if possible, and returns a pointer to the combined node...
static const LPoint3f & zero()
Returns a zero-length point.
Base class for objects that can be written to and read from Bam files.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
CharacterSlider * find_slider(const string &name) const
Returns a pointer to the slider with the given name, if there is such a slider, or NULL if there is n...
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
virtual void write(ostream &out, int indent_level) const
Writes a brief description of the bundle and all of its descendants.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
CharacterJoint * find_joint(const string &name) const
Returns a pointer to the joint with the given name, if there is such a joint, or NULL if there is no ...
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
virtual void write_with_value(ostream &out, int indent_level) const
Writes a brief description of the group, showing its current value, and that of all of its descendant...
This is a specialization on VertexSlider that returns the slider value associated with a particular C...
This is an abstract base class that retains some slider value, which is a linear value that typically...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
bool add_net_transform(PandaNode *node)
Adds the indicated node to the list of nodes that will be updated each frame with the joint's net tra...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
This is a morph slider within the character.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
This is a trivial class returned by PartBundleNode::get_bundle().
void update_to_now()
Advances the character's frame to the current time, and then calls update().
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
bool force_update()
Updates all the parts in the bundle to reflect the data for the current frame, whether we believe it ...
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node...
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
bool add_local_transform(PandaNode *node)
Adds the indicated node to the list of nodes that will be updated each frame with the joint's local t...
A lightweight class that represents a single element that may be timed and/or counted via stats...
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
int get_child_sort(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the sort index of the nth child node of this node (that is, the number that was passed to add...
This is a node that contains a pointer to an PartBundle.
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed, if it was set by set_cull_cent...
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of child nodes this node has.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
int get_frame_count(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of times tick() has been called since the ClockObject was created, or since it was last reset.
A container for geometry primitives.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void set_update_delay(double delay)
Specifies the minimum amount of time, in seconds, that should elapse between any two consecutive upda...
const CharacterSlider * get_char_slider() const
Returns the CharacterSlider object for which this object returns the slider value.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual PandaNode * dupe_for_flatten() const
This is similar to make_copy(), but it makes a copy for the specific purpose of flatten.
const RenderState * get_geom_state(int n) const
Returns the RenderState associated with the nth geom of the node.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
void set_lod_animation(const LPoint3 ¢er, PN_stdfloat far_distance, PN_stdfloat near_distance, PN_stdfloat delay_factor)
Activates a special mode in which the character animates less frequently as it gets further from the ...
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
PandaNode * get_child(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth child node of this node.
PartGroup * get_child(int n) const
Returns the nth child of the group.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
A thread; that is, a lightweight process.
This is the root of a MovingPart hierarchy.
This represents one joint of the character's animation, containing an animating transform matrix...
bool update()
Updates all the parts in the bundle to reflect the data for the current frame (as set in each of the ...
bool is_empty() const
Returns true if the NodePath contains no nodes.
void clear_lod_animation()
Undoes the effect of a recent call to set_lod_animation().
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
void force_update()
Recalculates the character even if we think it doesn't need it.
int get_num_children() const
Returns the number of child nodes of the group.
A class to retrieve the individual data elements previously stored in a Datagram. ...
Character * get_character() const
Returns the Character that owns this joint.
virtual bool is_geom_node() const
A simple downcast check.
TypeHandle is the identifier used to differentiate C++ class types.
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
void merge_anim_preloads(const PartBundle *other)
Copies the contents of the other PartBundle's preload table into this one.
void add_child(PandaNode *child_node, int sort=0, Thread *current_thread=Thread::get_current_thread())
Adds a new child to the node.
void write_part_values(ostream &out) const
Writes a list of the Character's joints and sliders, along with each current position, in their hierchical structure, to the indicated output stream.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
PartBundle * get_bundle()
Returns the actual PartBundle embedded within the handle.
static void register_with_read_factory()
Tells the BamReader how to create objects of type Character.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
A node that holds Geom objects, renderable pieces of geometry.
PartGroup * find_child(const string &name) const
Returns the first descendant found with the indicated name, or NULL if no such descendant exists...
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
int get_num_geoms() const
Returns the number of geoms in the node.
void merge_bundles(PartBundle *old_bundle, PartBundle *other_bundle)
Merges old_bundle with new_bundle.
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
void remove_all_geoms()
Removes all the geoms from the node at once.
This is the base class for PartRoot and MovingPart.