diff --git a/pandatool/src/egg-optchar/eggOptchar.cxx b/pandatool/src/egg-optchar/eggOptchar.cxx index 9e31022d87..7000ae74f8 100644 --- a/pandatool/src/egg-optchar/eggOptchar.cxx +++ b/pandatool/src/egg-optchar/eggOptchar.cxx @@ -185,7 +185,7 @@ run() { // Now we can analyze the joints for their properties. for (ci = 0; ci < num_characters; ci++) { EggCharacterData *char_data = _collection->get_character(ci); - analyze_joints(char_data->get_root_joint()); + analyze_joints(char_data->get_root_joint(), 0); analyze_sliders(char_data); } @@ -419,7 +419,7 @@ determine_removed_components() { for (int ci = 0; ci < num_characters; ci++) { EggCharacterData *char_data = _collection->get_character(ci); int num_components = char_data->get_num_components(); - cerr << char_data->get_name() << " has " << num_components << " components.\n"; + nout << char_data->get_name() << " has " << num_components << " components.\n"; for (int i = 0; i < num_components; i++) { EggComponentData *comp_data = char_data->get_component(i); nassertv(comp_data != (EggComponentData *)NULL); @@ -446,7 +446,19 @@ determine_removed_components() { } else { // Remove this component if it's unanimated or empty. if ((user_data->_flags & (EggOptcharUserData::F_static | EggOptcharUserData::F_empty)) != 0) { - user_data->_flags |= EggOptcharUserData::F_remove; + if ((user_data->_flags & (EggOptcharUserData::F_top | EggOptcharUserData::F_empty)) == EggOptcharUserData::F_top) { + // Actually, we can't remove it if it's a top joint, + // unless it's also empty. That's because vertices that + // are partially assigned to this joint would then have no + // joint to represent the same partial assignment, and + // they would then appear to be wholly assigned to their + // other joint, which would be incorrect. + + } else { + // But joints that aren't top joints (or that are empty) + // are o.k. to remove. + user_data->_flags |= EggOptcharUserData::F_remove; + } } } } @@ -523,7 +535,6 @@ move_vertices() { //////////////////////////////////////////////////////////////////// bool EggOptchar:: process_joints() { - cerr << "process_joints\n"; bool removed_any = false; int num_characters = _collection->get_num_characters(); for (int ci = 0; ci < num_characters; ci++) { @@ -772,10 +783,17 @@ zero_channels() { // joint. //////////////////////////////////////////////////////////////////// void EggOptchar:: -analyze_joints(EggJointData *joint_data) { +analyze_joints(EggJointData *joint_data, int level) { PT(EggOptcharUserData) user_data = new EggOptcharUserData; joint_data->set_user_data(user_data); + if (level == 1) { + // The child joints of the root joint are deemed "top" joints. + // These may not be removed unless they are empty (because their + // vertices have no joint to be moved into). + user_data->_flags |= EggOptcharUserData::F_top; + } + // Analyze the table of matrices for this joint, checking to see if // they're all the same across all frames, or if any of them are // different; also look for empty joints (that control no vertices). @@ -831,7 +849,7 @@ analyze_joints(EggJointData *joint_data) { int num_children = joint_data->get_num_children(); for (i = 0; i < num_children; i++) { - analyze_joints(joint_data->get_child(i)); + analyze_joints(joint_data->get_child(i), level + 1); } } @@ -999,6 +1017,9 @@ describe_component(EggComponentData *comp_data, int indent_level, if (user_data->is_empty()) { cout << " (empty)"; } + if (user_data->is_top()) { + cout << " (top)"; + } } cout << "\n"; } diff --git a/pandatool/src/egg-optchar/eggOptchar.h b/pandatool/src/egg-optchar/eggOptchar.h index efbeb098e6..8ca204a991 100644 --- a/pandatool/src/egg-optchar/eggOptchar.h +++ b/pandatool/src/egg-optchar/eggOptchar.h @@ -64,7 +64,7 @@ private: bool apply_user_reparents(); bool zero_channels(); - void analyze_joints(EggJointData *joint_data); + void analyze_joints(EggJointData *joint_data, int level); void analyze_sliders(EggCharacterData *char_data); void list_joints(EggJointData *joint_data, int indent_level, bool verbose); void list_joints_p(EggJointData *joint_data, int &col); diff --git a/pandatool/src/egg-optchar/eggOptcharUserData.I b/pandatool/src/egg-optchar/eggOptcharUserData.I index 8233b87081..eb6802d3dd 100644 --- a/pandatool/src/egg-optchar/eggOptcharUserData.I +++ b/pandatool/src/egg-optchar/eggOptcharUserData.I @@ -87,3 +87,13 @@ INLINE bool EggOptcharUserData:: is_empty() const { return (_flags & F_empty) != 0; } + +//////////////////////////////////////////////////////////////////// +// Function: EggOptcharUserData::is_top +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool EggOptcharUserData:: +is_top() const { + return (_flags & F_top) != 0; +} diff --git a/pandatool/src/egg-optchar/eggOptcharUserData.h b/pandatool/src/egg-optchar/eggOptcharUserData.h index 438ac914dd..68bcff70f2 100644 --- a/pandatool/src/egg-optchar/eggOptcharUserData.h +++ b/pandatool/src/egg-optchar/eggOptcharUserData.h @@ -38,13 +38,15 @@ public: INLINE bool is_static() const; INLINE bool is_identity() const; INLINE bool is_empty() const; + INLINE bool is_top() const; enum Flags { F_static = 0x0001, F_identity = 0x0002, F_empty = 0x0004, - F_remove = 0x0008, - F_expose = 0x0010, + F_top = 0x0008, + F_remove = 0x0010, + F_expose = 0x0020, }; int _flags; LMatrix4d _static_mat;