No SkeletonAnimation::setWeight(Real) function?

Minor issues with the Ogre API that can be trivial to fix
Post Reply
Dugi
Halfling
Posts: 46
Joined: Tue Jul 23, 2013 2:37 pm
x 7

No SkeletonAnimation::setWeight(Real) function?

Post by Dugi »

When porting my program to Ogre 2.1 API, I noticed a function that I sorely miss. It's available for the old v1::AnimationState, allowing to set the animation's weight to all bones at once. However, SkeletonAnimation has no such function, only the setBoneWeight function that does it only for one bone.

It is possible to iterate through all bones and set it one by one, but it requires one string lookup for each bone that is quite slow. The bone weights seem to be saved one after another in an array, so they could be changed all pretty fast.

I'd make a Pull Request for it, but I can't quite make sense of the pointer magic used there. Iterating through the bones and editing on the addresses as that function calculates is an easy, but not the optimal solution. Something like this:

Code: Select all

	void SkeletonAnimation::setWeight(  Real weight )
	{
		for (map<IdString, size_t>::type::const_iterator itor = mDefinition->mBoneWeights.begin(); itor != mDefinition->mBoneWeights.end(); ++itor)
		{
			size_t level    = itor->second >> 24;
			size_t offset   = itor->second & 0x00FFFFFF;
			Real *aliasedBoneWeights = reinterpret_cast<Real*>( mBoneWeights.get() ) +
												offset + (*mSlotStarts)[level];
			*aliasedBoneWeights = weight;
		}
	}
	//-----------------------------------------------------------------------------------
	Real SkeletonAnimation::getWeight()
	{
		Real total = 0;
		int divisor = 0;
		for (map<IdString, size_t>::type::const_iterator itor = mDefinition->mBoneWeights.begin(); itor != mDefinition->mBoneWeights.end(); ++itor)
		{
			size_t level    = itor->second >> 24;
			size_t offset   = itor->second & 0x00FFFFFF;
			Real *aliasedBoneWeights = reinterpret_cast<Real*>( mBoneWeights.get() ) +
												offset + (*mSlotStarts)[level];
			total += *aliasedBoneWeights;
			divisor++;
		}
		return total / divisor;
	}
I need it because I am using a trick to blend an ending animation with the following one that I set the old animation's weight progressively to 0 while the new one's weight is increased progressively to 1, which works pretty well, but the new complexity of this operation could create a bottleneck.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: No SkeletonAnimation::setWeight(Real) function?

Post by dark_sylinc »

You're overthinking it.
You missed that SkeletonAnimation::mWeight is public.

Just modify it directly and you're good to go. Same with mWeight & mLoop.
The rule of thumb if a variable needs a setter and getter which are trivial, then the variables should be public in the first place unless it would make practical sense using a setter (i.e. placing breakpoints inside the setter)

Mental note: Why are some variables there that shouldn't be public... public? (such as mEnabled)
Dugi
Halfling
Posts: 46
Joined: Tue Jul 23, 2013 2:37 pm
x 7

Re: No SkeletonAnimation::setWeight(Real) function?

Post by Dugi »

Yes, this makes very much sense. Better than a zillion setters for nothing. I was just used to see setters everywhere.

Sorry for annoying.
Post Reply