diff --git a/panda/src/egg/eggGroup.I b/panda/src/egg/eggGroup.I index 23e2f7ccbf..9d4bbfced4 100644 --- a/panda/src/egg/eggGroup.I +++ b/panda/src/egg/eggGroup.I @@ -238,6 +238,18 @@ get_dcs_type() const { return (DCSType)(_flags2 & F2_dcs_type); } +//////////////////////////////////////////////////////////////////// +// Function: EggGroup::has_dcs_type +// Access: Public +// Description: Returns true if the specified DCS type is not +// DC_none and not DC_unspecified. +//////////////////////////////////////////////////////////////////// +INLINE bool EggGroup:: +has_dcs_type() const { + DCSType type = get_dcs_type(); + return (type != DC_none && type != DC_unspecified); +} + //////////////////////////////////////////////////////////////////// // Function: EggGroup::set_dart_type // Access: Public diff --git a/panda/src/egg/eggGroup.cxx b/panda/src/egg/eggGroup.cxx index b1bff26c8a..f47120db8d 100644 --- a/panda/src/egg/eggGroup.cxx +++ b/panda/src/egg/eggGroup.cxx @@ -306,7 +306,7 @@ write_collide_flags(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// void EggGroup:: write_model_flags(ostream &out, int indent_level) const { - if (get_dcs_type() != DC_none) { + if (get_dcs_type() != DC_unspecified) { indent(out, indent_level) << " { " << get_dcs_type() << " }\n"; } @@ -783,19 +783,21 @@ string_dart_type(const string &string) { // Function: EggGroup::string_dcs_type // Access: Public, Static // Description: Returns the DCSType value associated with the given -// string representation, or DC_none if the string -// does not match any known DCSType value. +// string representation, or DC_unspecified if the +// string does not match any known DCSType value. //////////////////////////////////////////////////////////////////// EggGroup::DCSType EggGroup:: string_dcs_type(const string &string) { - if (cmp_nocase_uh(string, "local") == 0) { + if (cmp_nocase_uh(string, "none") == 0) { + return DC_none; + } else if (cmp_nocase_uh(string, "local") == 0) { return DC_local; } else if (cmp_nocase_uh(string, "net") == 0) { return DC_net; } else if (cmp_nocase_uh(string, "default") == 0) { return DC_default; } else { - return DC_none; + return DC_unspecified; } } @@ -1163,6 +1165,8 @@ ostream &operator << (ostream &out, EggGroup::DartType t) { //////////////////////////////////////////////////////////////////// ostream &operator << (ostream &out, EggGroup::DCSType t) { switch (t) { + case EggGroup::DC_unspecified: + return out << "unspecified"; case EggGroup::DC_none: return out << "none"; case EggGroup::DC_local: diff --git a/panda/src/egg/eggGroup.h b/panda/src/egg/eggGroup.h index 82ce25d34b..98347f7db6 100644 --- a/panda/src/egg/eggGroup.h +++ b/panda/src/egg/eggGroup.h @@ -59,10 +59,11 @@ PUBLISHED: }; enum DCSType { // The bits here must correspond to those in Flags2, below. - DC_none = 0x00000000, - DC_local = 0x00000010, - DC_net = 0x00000020, - DC_default = 0x00000030, + DC_unspecified = 0x00000000, + DC_none = 0x00000010, + DC_local = 0x00000020, + DC_net = 0x00000030, + DC_default = 0x00000040, }; enum BillboardType { // The bits here must correspond to those in Flags, below. @@ -147,6 +148,7 @@ PUBLISHED: INLINE void set_dcs_type(DCSType type); INLINE DCSType get_dcs_type() const; + INLINE bool has_dcs_type() const; INLINE void set_dart_type(DartType type); INLINE DartType get_dart_type() const; @@ -279,11 +281,11 @@ private: F2_into_collide_mask = 0x00000004, F2_billboard_center = 0x00000008, - F2_dcs_type = 0x00000030, - F2_portal_flag = 0x00000040, - F2_polylight_flag = 0x00000080, - F2_indexed_flag = 0x00000100, - F2_has_indexed_flag = 0x00000200, + F2_dcs_type = 0x00000070, + F2_portal_flag = 0x00000080, + F2_polylight_flag = 0x00000100, + F2_indexed_flag = 0x00000200, + F2_has_indexed_flag = 0x00000400, }; int _flags; diff --git a/panda/src/egg/parser.yxx b/panda/src/egg/parser.yxx index 5864dfdb0c..41fa161991 100644 --- a/panda/src/egg/parser.yxx +++ b/panda/src/egg/parser.yxx @@ -1209,7 +1209,7 @@ group_body: string strval = $4; EggGroup::DCSType f = EggGroup::string_dcs_type(strval); - if (f == EggGroup::DC_none) { + if (f == EggGroup::DC_unspecified) { eggyywarning("Unknown DCS type " + strval); } else { group->set_dcs_type(f); diff --git a/panda/src/egg2pg/characterMaker.cxx b/panda/src/egg2pg/characterMaker.cxx index a30b20b6b2..8f4aa88511 100644 --- a/panda/src/egg2pg/characterMaker.cxx +++ b/panda/src/egg2pg/characterMaker.cxx @@ -287,7 +287,7 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part) { index = _parts.size(); _parts.push_back(joint); - if (egg_group->get_dcs_type() != EggGroup::DC_none) { + if (egg_group->has_dcs_type()) { // If the joint requested an explicit DCS, create a node for // it. PT(ModelNode) geom_node = new ModelNode(egg_group->get_name()); @@ -556,7 +556,7 @@ determine_primitive_home(EggPrimitive *egg_primitive) { if (egg_group != (EggGroup *)NULL && egg_group->get_group_type() == EggGroup::GT_joint && - egg_group->get_dcs_type() == EggGroup::DC_none) { + !egg_group->has_dcs_type()) { // If the home is a joint without a flag--this is the normal // case--we'll move the polygon under the character node and // animate it from there explicitly. @@ -673,15 +673,21 @@ determine_bin_home(EggBin *egg_bin) { if (egg_group != (EggGroup *)NULL && egg_group->get_group_type() == EggGroup::GT_joint && - egg_group->get_dcs_type() == EggGroup::DC_none) { + !egg_group->has_dcs_type()) { // If we have rigid geometry that is assigned to a joint without a // flag, which means the joint didn't get created as its own // node, go ahead and make an implicit node for the joint. - - // The alternative is to return NULL to treat the geometry as - // dynamic (and animate it by animating its vertices), but display - // lists and vertex buffers will perform better if as much - // geometry as possible is rigid. + + if (egg_group->get_dcs_type() == EggGroup::DC_none) { + // Unless the user specifically forbade exposing the joint by + // putting an explicit " { none }" entry in the joint. In + // this case, we return NULL to treat the geometry as dynamic + // (and animate it by animating its vertices), but display lists + // and vertex buffers will perform better if as much geometry as + // possible is rigid. + return NULL; + } + CharacterJoint *joint; DCAST_INTO_R(joint, egg_to_part(egg_group), home); egg_group->set_dcs_type(EggGroup::DC_default); diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 3729f33265..01a95d7826 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1747,8 +1747,7 @@ make_node(EggGroup *egg_group, PandaNode *parent) { make_node(*ci, node); } - } else if (egg_group->get_model_flag() || - egg_group->get_dcs_type() != EggGroup::DC_none) { + } else if (egg_group->get_model_flag() || egg_group->has_dcs_type()) { // A model or DCS flag; create a model node. node = new ModelNode(egg_group->get_name()); switch (egg_group->get_dcs_type()) { @@ -1762,6 +1761,7 @@ make_node(EggGroup *egg_group, PandaNode *parent) { break; case EggGroup::DC_none: + case EggGroup::DC_unspecified: break; } diff --git a/pandatool/src/egg-optchar/eggOptchar.cxx b/pandatool/src/egg-optchar/eggOptchar.cxx index d984db9982..92cc05bee6 100644 --- a/pandatool/src/egg-optchar/eggOptchar.cxx +++ b/pandatool/src/egg-optchar/eggOptchar.cxx @@ -91,6 +91,15 @@ EggOptchar() { "and objects can be parented to it. This implies -keep.", &EggOptchar::dispatch_vector_string_comma, NULL, &_expose_components); + add_option + ("suppress", "joint[,joint...]", 0, + "The opposite of suppress, this prevents the named joints from " + "being created with an implicit DCS attribute, even if they contain " + "rigid geometry. The default is to create an implicit node for any " + "joint that contains rigid geometry, to take advantage of display " + "list and/or vertex buffer caching. This does not imply -keep.", + &EggOptchar::dispatch_vector_string_comma, NULL, &_suppress_components); + add_option ("flag", "node[,node...][=name]", 0, "Assign the indicated name to the geometry within the given nodes. " @@ -471,6 +480,7 @@ determine_removed_components() { Names keep_names; Names drop_names; Names expose_names; + Names suppress_names; Names names_used; vector_string::const_iterator si; @@ -484,6 +494,9 @@ determine_removed_components() { keep_names.insert(*si); expose_names.insert(*si); } + for (si = _suppress_components.begin(); si != _suppress_components.end(); ++si) { + suppress_names.insert(*si); + } // We always keep the root joint, which has no name. keep_names.insert(""); @@ -502,6 +515,13 @@ determine_removed_components() { nassertv(user_data != (EggOptcharUserData *)NULL); const string &name = comp_data->get_name(); + if (suppress_names.find(name) != suppress_names.end()) { + // If this component is not dropped, it will not be implicitly + // exposed. + names_used.insert(name); + user_data->_flags |= EggOptcharUserData::F_suppress; + } + if (drop_names.find(name) != drop_names.end()) { // Remove this component by user request. names_used.insert(name); @@ -557,6 +577,12 @@ determine_removed_components() { nout << "No such component: " << name << "\n"; } } + for (si = _suppress_components.begin(); si != _suppress_components.end(); ++si) { + const string &name = (*si); + if (names_used.find(name) == names_used.end()) { + nout << "No such component: " << name << "\n"; + } + } } //////////////////////////////////////////////////////////////////// @@ -649,6 +675,8 @@ process_joints() { joint_data->reparent_to(best_parent); if ((user_data->_flags & EggOptcharUserData::F_expose) != 0) { joint_data->expose(); + } else if ((user_data->_flags & EggOptcharUserData::F_suppress) != 0) { + joint_data->expose(EggGroup::DC_none); } num_kept++; } diff --git a/pandatool/src/egg-optchar/eggOptchar.h b/pandatool/src/egg-optchar/eggOptchar.h index 7d488e0293..d1fd8f50d0 100644 --- a/pandatool/src/egg-optchar/eggOptchar.h +++ b/pandatool/src/egg-optchar/eggOptchar.h @@ -100,6 +100,7 @@ private: vector_string _keep_components; vector_string _drop_components; vector_string _expose_components; + vector_string _suppress_components; class DoubleString { public: diff --git a/pandatool/src/egg-optchar/eggOptcharUserData.h b/pandatool/src/egg-optchar/eggOptcharUserData.h index 68bcff70f2..440c23525a 100644 --- a/pandatool/src/egg-optchar/eggOptcharUserData.h +++ b/pandatool/src/egg-optchar/eggOptcharUserData.h @@ -47,6 +47,7 @@ public: F_top = 0x0008, F_remove = 0x0010, F_expose = 0x0020, + F_suppress = 0x0040, }; int _flags; LMatrix4d _static_mat; diff --git a/pandatool/src/maxegg/maxToEggConverter.cxx b/pandatool/src/maxegg/maxToEggConverter.cxx index 2854aa1cd3..6c18a1bc3e 100755 --- a/pandatool/src/maxegg/maxToEggConverter.cxx +++ b/pandatool/src/maxegg/maxToEggConverter.cxx @@ -718,13 +718,13 @@ get_transform(INode *max_node, EggGroup *egg_group) { case TT_model: if (!egg_group->get_model_flag() && - egg_group->get_dcs_type() == EggGroup::DC_none) { + !egg_group->has_dcs_type()) { return; } break; case TT_dcs: - if (egg_group->get_dcs_type() == EggGroup::DC_none) { + if (!egg_group->get_dcs_type()) { return; } break; @@ -2415,4 +2415,4 @@ Modifier* MaxToEggConverter::FindSkinModifier (INode* node, const Class_ID &type // Not found. return NULL; -} \ No newline at end of file +} diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index a3d9c12092..8fdf8e558f 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/pandatool/src/mayaegg/mayaToEggConverter.cxx @@ -931,14 +931,13 @@ get_transform(MayaNodeDesc *node_desc, const MDagPath &dag_path, break; case TT_model: - if (!egg_group->get_model_flag() && - egg_group->get_dcs_type() == EggGroup::DC_none) { + if (!egg_group->get_model_flag() && !egg_group->has_dcs_type()) { return; } break; case TT_dcs: - if (egg_group->get_dcs_type() == EggGroup::DC_none) { + if (!egg_group->has_dcs_type()) { return; } break;