3939#include " dart/dynamics/Skeleton.hpp"
4040
4141#include < cassert>
42+ #include < cstdint>
4243
4344namespace dart {
4445namespace collision {
@@ -321,6 +322,31 @@ void CollisionGroup::removeDeletedShapeFrames()
321322 mObserver .mDeletedFrames .clear ();
322323}
323324
325+ // ==============================================================================
326+ std::size_t CollisionGroup::computeMetaSkeletonVersion (
327+ const dynamics::MetaSkeleton& metaSkeleton)
328+ {
329+ if (const auto * skeleton
330+ = dynamic_cast <const dynamics::Skeleton*>(&metaSkeleton)) {
331+ return skeleton->getVersion ();
332+ }
333+
334+ const std::size_t numBodies = metaSkeleton.getNumBodyNodes ();
335+ std::size_t seed = numBodies;
336+
337+ for (std::size_t i = 0u ; i < numBodies; ++i) {
338+ const auto * bodyNode = metaSkeleton.getBodyNode (i);
339+ const auto bodyNodeHash
340+ = static_cast <std::size_t >(reinterpret_cast <std::uintptr_t >(bodyNode));
341+ const auto bodyNodeVersion = bodyNode ? bodyNode->getVersion () : 0u ;
342+
343+ seed ^= bodyNodeHash + 0x9e3779b97f4a7c15ULL + (seed << 6 ) + (seed >> 2 );
344+ seed ^= bodyNodeVersion + 0x9e3779b97f4a7c15ULL + (seed << 6 ) + (seed >> 2 );
345+ }
346+
347+ return seed;
348+ }
349+
324350// ==============================================================================
325351void CollisionGroup::updateEngineData ()
326352{
@@ -449,18 +475,12 @@ bool CollisionGroup::updateSkeletonSource(SkeletonSources::value_type& entry)
449475 // This skeleton no longer exists, so we should remove all its contents from
450476 // the CollisionGroup.
451477 for (const auto & object : source.mObjects )
452- removeShapeFrameInternal (object.second ->mFrame , object .first );
478+ removeShapeFrameInternal (object.second ->mFrame , entry .first );
453479
454480 return true ;
455481 }
456482
457- // Note: Right now we can only subscribe to Skeletons, not MetaSkeletons, so
458- // we can safely do a static_cast here. Eventually this static_cast should not
459- // be needed, if we can figure out a versioning system for MetaSkeleton.
460- const dynamics::Skeleton* skeleton
461- = dynamic_cast <const dynamics::Skeleton*>(meta.get ());
462-
463- const std::size_t currentSkeletonVersion = skeleton->getVersion ();
483+ const std::size_t currentSkeletonVersion = computeMetaSkeletonVersion (*meta);
464484 // If the version hasn't changed, then there will be nothing to update.
465485 if (currentSkeletonVersion == source.mLastKnownVersion )
466486 return false ;
@@ -473,8 +493,8 @@ bool CollisionGroup::updateSkeletonSource(SkeletonSources::value_type& entry)
473493 // Check each child to see if its version number has changed. If it has, then
474494 // check to see if any of its ShapeFrames need to be updated, added, or
475495 // removed from the CollisionGroup.
476- for (std::size_t i = 0 ; i < skeleton ->getNumBodyNodes (); ++i) {
477- const dynamics::BodyNode* bn = skeleton ->getBodyNode (i);
496+ for (std::size_t i = 0 ; i < meta ->getNumBodyNodes (); ++i) {
497+ const dynamics::BodyNode* bn = meta ->getBodyNode (i);
478498 const std::size_t currentVersion = bn->getVersion ();
479499
480500 unusedChildren.erase (bn);
@@ -541,7 +561,8 @@ bool CollisionGroup::updateSkeletonSource(SkeletonSources::value_type& entry)
541561 }
542562 }
543563
544- // Remove from this group any BodyNodes that no longer belong to the skeleton
564+ // Remove from this group any BodyNodes that no longer belong to the meta
565+ // skeleton
545566 for (const auto & unusedChild : unusedChildren) {
546567 for (const dynamics::ShapeFrame* unusedFrame : unusedChild.second .mFrames ) {
547568 updateNeeded = true ;
0 commit comments