Extracting the RST from an AnimationSet

Started by
7 comments, last by 999999999 18 years, 9 months ago
I'm trying to extract all key frames from an animation controller. So I use ID3DXAnimationController::GetAnimationSet( i ); to get the animation set and then I'd like to loop through all the key frames in the set and extract their RST - this is where I'm stuck. The only way to get an RST is via ID3DXAnimationSet::GetSRT( ), but it takes in a period - which I believe is a time. I want to just index into it and grab all of them, not pass in the time. Anyway I can extract all keyframes? Thanks!
Advertisement
It seems that if I could change the ID3DXAnimationSet into it's derived class ID3DXKeyFramedAnimationSet, I would be able to get access to all the key frames through their method GetRotationKeys, GetScaleKeys, GetTranslationKeys, but I don't know how to go from the base AnimSet to the derived KeyFramedAnimSet.

Any help would be appreciated.
Well, I'm working on the same thing, I need keyframe data to transform the vertices on the CPU at loading time to calculate the animation bounding ellipsoid every keyframe. I began looking for this kind of information this morning and I think a way could be:
(I haven't undertood yet what this 'periodic position','period' is exactly - I have looked at Microsoft documentation)

// The point is: do you know your animation frame-rate?// If you do (e.g. 25 FPS) I think you could do this:for (int i = 0; i < keyFrameCount; i++){   // 1: Try to determine the local time value for the particular keyframe   double timeValue = (1.0 / 25.0) * (double)i; // ((double)i) / 25.0   // 2: Convert the local time value to periodic position   double periodicPosition = animSet->GetPeriodicPosition(timeValue);   // 3: Get SRT from the periodic position   animSet->GetSRT(periodicPosition,animIndex,&vScale,&qRot,&mTrans);   // 4: Use your data (you could only store data here in an array of vectors and quaternions}// If you do not have keyFrameCount you can, of course, calculate it://      keyFrameCount = 25 * animLenghtInSeconds;// or:  keyFrameCount = animSet->GetPeriod() * 25.0; // (animset->GetPeriod()/(1.0/25.0)


Not tried yet, I'll work on it in the next few days. Hope this helps.
I don't want to sound like a jackass, but if you guys saved half the time you put into understanding that animation controller, you could have built your own entire system that provides complete control. Not to mention that it's a blast of fun, compared to your average programming task.

I will be around to help if anyone ever decides to try.
I think I'd be able to create my own system but to me it seems a nightmare the file-parsing part. I don't want to spend months to build a working x-file reading and parsing system to get correct animation data.
I admit, that would be the nastiest part. Not difficult, but also not fun at all. However, once you write an x-file parser, you've got the only x-file parser you'll ever need. You can use it to load any type of x-file. Even make your own little tool to convert the animations over to your own format.

Just in case, here are some functions you'll want to look at:

D3DXFileCreate - start the whole process
ID3DXFile::RegisterTemplates - send ((VOID*)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)
ID3DXFile::CreateEnumObject - tell it how to open the file and such
ID3DXFileEnumObject::GetChildren - get number of objects in top level
ID3DXFileEnumObject::GetChild - get top object by index (call for each child)

Then for each top level object..

ID3DXFileData::GetType - to see what type of object it is
Some types are TID_D3DRMAnimationSet, TID_D3DRMAnimation, TID_D3DRMAnimationKey, TID_D3DRMMesh, TID_D3DRMFrame, and TID_D3DRMFrameTransformMatrix. Pay the most attention to TID_D3DRMFrame, because it is usually placed right before each object. Think of it as being like a bookmark showing the beginning of every new object. Each object after a frame belongs to the same object. The frame usually contains the name of the object, too.
ID3DXFileData::GetName - needed to sort some things out. Usually only frames have names.

After you process the object, call ID3DXFileData::GetChildren and ID3DXFileData::GetChild (for each child) again for that specific object until it has no further branches.

What I do is just wait for TID_D3DRMFrame objects, add a reference to that frame and then continue until I find something useful. When something useful pops up like an animation set or mesh, I look back to see what information the frame that I referenced contains, and store it all together as a single object. To actually load in objects like animation keys, you need ID3DXFileData::Lock. Then you have to process the returned data as a generic chunk of memory.

There's lots of help in the docs as well. Like the format of each generic memory chunk, depending on which type of object you're loading. In some cases, you can just pass the file object to D3DX functions and let it load it for you.
Thank you very much for the information, but (for ph33r) do you think that what I wrote before could work?
You're asking me? [smile]

I have no idea, I've never used the animation controller. It looks like you're using the index to calculate the time for that frame? To be honest, I don't understand what GetPeriodicPosition does. Does it snap the time to a frame? If so, I can't imagine why it wouldn't work correctly.
I don't know exactly but here's what Microsoft says about GetPeriodicPosition:
Quote:
ID3DXAnimationSet::GetPeriodicPosition

Returns time position in the local timeframe of an animation set.

Syntax:
DOUBLE GetPeriodicPosition(DOUBLE Position);

Parameters:
Position
Local time of the animation set.

Return Value:
Time position as measured in the timeframe of the animation set. This value will be bounded by the period of the animation set.

Remarks:
The time position returned by this method can be used as the PeriodicPosition parameter of ID3DXAnimationSet::GetSRT.

This topic is closed to new replies.

Advertisement