15 #include "characterMaker.h"
16 #include "eggLoader.h"
17 #include "config_egg2pg.h"
18 #include "eggBinner.h"
20 #include "eggPrimitive.h"
22 #include "partGroup.h"
23 #include "characterJoint.h"
24 #include "characterJointBundle.h"
25 #include "characterSlider.h"
26 #include "character.h"
28 #include "transformState.h"
29 #include "eggSurface.h"
31 #include "modelNode.h"
32 #include "characterVertexSlider.h"
33 #include "jointVertexTransform.h"
34 #include "userVertexTransform.h"
35 #include "eggAnimPreload.h"
36 #include "animPreloadTable.h"
49 : _loader(loader), _egg_root(root) {
51 _character_node =
new Character(_egg_root->get_name());
52 _bundle = _character_node->get_bundle(0);
55 _skeleton_root =
new PartGroup(_bundle,
"<skeleton>");
56 _structured = structured;
67 return _character_node;
77 return _egg_root->get_name();
96 nassertr(index < (
int)_parts.size(), NULL);
114 return get_identity_transform();
117 VertexTransforms::iterator vi = _vertex_transforms.find(index);
118 if (vi != _vertex_transforms.end()) {
124 DCAST_INTO_R(joint, part, get_identity_transform());
127 _vertex_transforms[index] = vt;
140 NodeMap::const_iterator nmi = _node_map.find(egg_node);
141 if (nmi == _node_map.end()) {
144 return (*nmi).second;
159 if (part->
is_of_type(CharacterJoint::get_class_type())) {
161 if (joint->_geom_node != (
PandaNode *)NULL) {
162 node = joint->_geom_node;
176 if (child->
is_geom_node() && child->get_name() == name) {
195 _morph_root =
new PartGroup(_bundle,
"morph");
198 int index = _parts.size();
199 _parts.push_back(slider);
211 VertexSliders::iterator vi = _vertex_sliders.find(name);
212 if (vi != _vertex_sliders.end()) {
219 _vertex_sliders[name] = slider;
231 build_joint_hierarchy(_egg_root, _skeleton_root, -1);
235 make_geometry(_egg_root);
237 _bundle->sort_descendants();
238 parent_joint_nodes(_skeleton_root);
253 void CharacterMaker::
255 if (egg_node->
is_of_type(EggAnimPreload::get_class_type())) {
259 if (egg_anim_preload->has_fps()) {
260 fps = egg_anim_preload->
get_fps();
264 if (egg_anim_preload->has_num_frames()) {
271 _bundle->set_anim_preload(anim_preload);
273 anim_preload->add_anim(egg_node->get_name(), fps, num_frames);
277 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
282 if (egg_group->get_group_type() == EggGroup::GT_joint) {
295 LMatrix4 matf = LCAST(PN_stdfloat, matd);
298 new CharacterJoint(_character_node, _character_node->get_bundle(0),
299 part, egg_group->get_name(), matf);
300 index = _parts.size();
301 _parts.push_back(joint);
308 matf = LCAST(PN_stdfloat, matd);
309 joint->_default_value = matf;
310 joint->_value = matf;
320 geom_node->set_preserve_transform(
ModelNode::PT_net);
322 joint->_geom_node = geom_node.p();
329 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
330 build_joint_hierarchy((*ci), part, index);
334 _node_map[egg_node] = index;
344 void CharacterMaker::
346 if (part->
is_of_type(CharacterJoint::get_class_type())) {
348 PandaNode *joint_node = joint->_geom_node;
349 if (joint_node != NULL) {
350 _character_node->add_child(joint_node);
352 joint_node->
set_transform(TransformState::make_mat(joint->_net_transform));
369 void CharacterMaker::
370 make_geometry(
EggNode *egg_node) {
371 if (egg_node->
is_of_type(EggBin::get_class_type())) {
374 if (!egg_bin->empty() &&
375 (egg_bin->get_bin_number() == EggBinner::BN_polyset ||
376 egg_bin->get_bin_number() == EggBinner::BN_patches)) {
383 bin_home = _egg_root;
396 _loader.
make_polyset(egg_bin, parent, &transform, is_dynamic,
401 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
404 EggGroupNode::const_iterator ci;
405 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
431 EggPrimitive::const_iterator vi;
432 for (vi = egg_primitive->begin();
433 vi != egg_primitive->end();
442 if (!vertex->_dxyzs.empty() ||
443 !vertex->_dnormals.empty() ||
444 !vertex->_drgbas.empty()) {
451 if (!(*uvi)->_duvs.empty()) {
463 vertex_home = egg_primitive->get_parent();
465 nassertr(vertex->
gref_size() == 1, NULL);
470 if (home != NULL && home != vertex_home) {
481 nassertr(home != NULL, NULL);
489 if (home->
is_of_type(EggGroup::get_class_type())) {
492 while (egg_group != (
EggGroup *)NULL &&
493 egg_group->get_group_type() != EggGroup::GT_joint &&
494 egg_group->get_dart_type() == EggGroup::DT_none) {
495 nassertr(egg_group->get_parent() != (
EggGroupNode *)NULL, NULL);
496 home = egg_group->get_parent();
498 if (home->
is_of_type(EggGroup::get_class_type())) {
503 if (egg_group != (
EggGroup *)NULL &&
504 egg_group->get_group_type() == EggGroup::GT_joint &&
528 determine_bin_home(
EggBin *egg_bin) {
538 if (!egg_rigid_geometry) {
548 EggGroupNode::const_iterator ci;
549 for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
552 EggPrimitive::const_iterator vi;
553 for (vi = egg_primitive->begin();
554 vi != egg_primitive->end();
563 if (!vertex->_dxyzs.empty() ||
564 !vertex->_dnormals.empty() ||
565 !vertex->_drgbas.empty()) {
572 if (!(*uvi)->_duvs.empty()) {
584 vertex_home = egg_primitive->get_parent();
586 nassertr(vertex->
gref_size() == 1, NULL);
591 if (home != NULL && home != vertex_home) {
604 nassertr(home != NULL, NULL);
612 if (home->
is_of_type(EggGroup::get_class_type())) {
615 while (egg_group != (
EggGroup *)NULL &&
616 egg_group->get_group_type() != EggGroup::GT_joint &&
617 egg_group->get_dart_type() == EggGroup::DT_none) {
618 nassertr(egg_group->get_parent() != (
EggGroupNode *)NULL, NULL);
619 home = egg_group->get_parent();
621 if (home->
is_of_type(EggGroup::get_class_type())) {
626 if (egg_group != (
EggGroup *)NULL &&
627 egg_group->get_group_type() == EggGroup::GT_joint &&
633 if (egg_group->get_dcs_type() == EggGroup::DC_none) {
649 egg_group->set_dcs_type(EggGroup::DC_default);
652 geom_node->set_preserve_transform(
ModelNode::PT_local);
653 joint->_geom_node = geom_node.p();
666 get_identity_transform() {
670 return _identity_transform;
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
string get_name() const
Returns the name of the character.
A basic node of the scene graph or data graph.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
This table records data about a list of animations for a particular model, such as number of frames a...
This is a 4-by-4 transform matrix.
const EggTransform & get_default_pose() const
Returns a read-only accessor to the initial pose transform.
The collection of all the joints and sliders in the character.
An animated character, with skeleton-morph animation and either soft-skinned or hard-skinned vertices...
A base class for nodes in the hierarchy that are not leaf nodes.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
bool has_dcs_type() const
Returns true if the specified DCS type is not DC_none and not DC_unspecified.
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...
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 morph slider within the character.
GroupRef::const_iterator gref_begin() const
Returns an iterator that can, in conjunction with gref_end(), be used to traverse the entire set of g...
VertexSlider * egg_to_slider(const string &name)
Returns the VertexSlider corresponding to the indicated egg slider name.
int create_slider(const string &name)
Creates a new morph slider of the given name, and returns its index.
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex...
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex...
int egg_to_index(EggNode *egg_node) const
Returns the index number associated with the PartGroup node for the given egg node, or -1.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
This node is placed at key points within the scene graph to indicate the roots of "models": subtrees ...
This is a 4-by-4 transform matrix.
This corresponds to an <AnimPreload> entry.
static const LMatrix4d & ident_mat()
Returns an identity matrix.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
const LMatrix4d & get_vertex_frame() const
Returns the coordinate frame of the vertices referenced by primitives at or under this node...
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of child nodes this node has.
int get_num_frames() const
This is only valid if has_num_frames() returns true.
PartGroup * egg_to_part(EggNode *egg_node) const
Returns the PartGroup node associated with the given egg node.
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.
A base class for things that may be directly added into the egg hierarchy.
This represents one joint of the character's animation, containing an animating transform matrix...
PandaNode * part_to_node(PartGroup *part, const string &name) const
Returns the scene graph node associated with the given PartGroup node, if there is one...
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.
VertexTransform * egg_to_transform(EggNode *egg_node)
Returns a JointVertexTransform suitable for applying the animation associated with the given egg node...
Converts an EggGroup hierarchy, beginning with a group with <Dart> set, to a character node with join...
virtual bool is_geom_node() const
A simple downcast check.
GroupRef::size_type gref_size() const
Returns the number of elements between gref_begin() and gref_end().
void add_child(PandaNode *child_node, int sort=0, Thread *current_thread=Thread::get_current_thread())
Adds a new child to the node.
void set_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Sets the transform that will be applied to this node and below.
A node that holds Geom objects, renderable pieces of geometry.
const LMatrix4d & get_node_frame_inv() const
Returns the inverse of the matrix returned by get_node_frame().
void make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform, bool is_dynamic, CharacterMaker *character_maker)
Creates a polyset–that is, a Geom–from the primitives that have already been grouped into a bin...
Converts an egg data structure, possibly read from an egg file but not necessarily, into a scene graph suitable for rendering.
A type of group node that holds related subnodes.
double get_fps() const
This is only valid if has_fps() returns true.
This is the base class for PartRoot and MovingPart.