Archived

This topic is now archived and is closed to further replies.

JudgeX

MS3D code and Advanced Animation

Recommended Posts

Now that the problems with the normal animation have been taken care of, I''ve started looking into handling an actual usable form of animations. However, I need some input and some help before I begin a full implementation. The first option I came up with was to fill a model with about 300 frames using different imported SMD files from half-life (and creating my own using the 3dsMAX SMD exporter). Of course, then, I''d need a way to use Bret''s awesome code to play the animation from frame x to frame y on command, which seems really difficult (I don''t think there''s an easy way to throw in a couple of paramaters on the existing functions or anything, it looks like almost a whole rework of the animation portion of the loading code). My second idea was to forego having frames whatsoever in the milkshape file, and manually importing the SMD files by adding in an importer. Don''t laugh too hard yet, try opening an SMD file, they''re simple text, a list of bones and coordinates at each frame... that''s it. This seems like it would be fairly easy to do, and it would be more versatile, as the models would be far smaller, and many models could share many animations. I really can''t figure out which of these two ideas would be most difficult to implement, and I''m looking for a lot of help here. Honestly, I see advantages to both of them, the first one seems slightly easier to implement(though I have no clue how at the moment and would REALLY appreciate input) and the second seems more difficult to implement, but with larger payoff, since you could dynamically load the animations and put the models through them. Any input will be greatly appreciated. Thanks, JudgeX

Share this post


Link to post
Share on other sites
Hi,

The latest version of PortaLib started to introduce support for multiple animations. I''ve asked Mete if he''ll hadd this feature to MS3D but haven''t heard back.

You could make 2 modifications to the system to get it to do what you want: 1 is to load multiple MS3D files into one Object3D and store the animations. Only load the model vertices once. This would work well with SMDs since when MS3D decompiles it it builds one model MS3D file and a bunch of animation files.

The other way is to modify the one animation after loading, splitting it into several based on keyframes.

The support is weak for now (no way to select which one yet - but easy to do). I am planning on doing an MD3 loader and implementing it at the same time. What do you think?

Now that I''m not bug hunting, feature requests sound good

~~~
Cheers!
Brett Porter
PortaLib3D : A portable 3D game/demo libary for OpenGL

Share this post


Link to post
Share on other sites
I like the idea of an md3 loader, myself, but I actually think the ms3d loader being modified to take in the smd keyframe information directly from smd''s would be the most versatile and useful thing ever. At the beginning of the program, you could just load up all your SMD keyframes, and then apply them to the skeletons whenever. This seems really nice to me, and I''m not sure how md3''s work.


Okay, how would I split the long animation into keyframes? I have a couple models that have 190 frames that load fine, but I need to play say, frame 32 to frame 70 to show the model do a running longjump.

I''m also interested in the other method... what is an Object3D? How could I implement loading the smd animations into a model straight from the smd file? I''m pretty good at file I/O, so, I think I could handle getting the data, but, I don''t know how to work it in conjunction with the timing, or exactly where to put the movement info for each joint (or if I have to do anything with normals, and so on).

Any input at all would be helpful

Thanks,
JudgeX

Share this post


Link to post
Share on other sites
Hi again!

Object3D is in PortaLib3D. It''s another abstraction to allow better handling of models with shadows and animation.

You can probably load an SMD into that to create the appropriate animation. If you can find a detailed file format for SMD I''ll put together a loader - how does that sound? Other than that I''ll do MD3 because it is more recent and I think does the same and more.

Splitting a long animation would involve pulling chunks out of the existing set of keyframe data and splitting the array.

HTH...

~~~
Cheers!
Brett Porter
PortaLib3D : A portable 3D game/demo libary for OpenGL

Share this post


Link to post
Share on other sites
hehe, I think I could almost do a detailed description of the SMD format myself .

Here goes...

It starts with version number, like this (literally like this):

version 1

then, lists the nodes (like this - when I say that, I''m taking it right from the file):

nodes
0 "Bip01" -1
1 "Bip01 Footsteps" 0
2 "Bip01 Pelvis" 0
3 "Bip01 L Leg" 2
4 "Bip01 L Leg1" 3
5 "Bip01 L Foot" 4
6 "Bip01 L Toe0" 5
7 "Bip01 L Toe01" 6
8 "Bip01 L Toe02" 7
9 "Dummy16" 8
10 "Bip01 R Leg" 2
11 "Bip01 R Leg1" 10
12 "Bip01 R Foot" 11
13 "Bip01 R Toe0" 12
14 "Bip01 R Toe01" 13
15 "Bip01 R Toe02" 14


--- And it goes on through the rest of them... I don''t know exactly how to use number is beside each of those, as it always indicates the bone before it in the hierarchy.

After all those it has an "end" and "skeleton" as shown:

end
skeleton

then it goes into the first time, and starts showing the various movements, listed by the number in front of each bone as listed above, followed by 6 numbers. Since I don''t really, truly know how bones work, I''m not sure what these numbers are. I''m pretty sure it''s x, y, z position and orientation. It looks like this:

time 1
0 0.233849 -0.404778 39.769844 0.000000 0.000000 -1.570795
1 -0.000000 -0.000000 -39.769844 0.000000 0.000000 1.570795
2 -0.000000 -0.000000 0.000000 -1.570795 -1.570796 0.000000
3 -0.000005 0.000007 3.713255 -0.015828 3.120255 -0.742554
4 18.045723 0.000000 0.000000 0.000000 0.000000 -0.835961
5 17.597597 0.000001 0.000000 -0.000583 0.026559 0.175834
6 3.793089 6.407222 0.000000 -0.000000 -0.000000 1.570796
7 0.935739 -0.000000 0.000000 0.000000 0.000000 0.000000
8 0.935741 -0.000000 0.000000 0.000000 0.000000 0.000000
9 0.935740 0.000000 0.000000 -0.000000 -0.000000 3.141593
10 0.000005 -0.000003 -3.713255 -0.009092 -3.126596 0.376169
11 18.045721 0.000000 -0.000000 0.000000 -0.000000 -0.799382
12 17.597597 -0.000001 0.000000 0.016928 0.004586 -0.490899
13 3.793090 6.407223 -0.000000 -0.000000 -0.000000 1.570796
14 0.935741 -0.000002 0.000000 0.000000 0.000000 0.000000
15 0.935740 0.000000 -0.000000 0.000000 0.000000 0.000000
16 0.935740 0.000001 -0.000000 0.000000 0.000000 0.000000

and continues to the last bone.

then goes into time 2 immediately

time 2
0 0.233849 -8.729897 39.109177 0.000000 0.000000 -1.570795
1 0.000000 0.000000 -39.109177 0.000000 0.000000 1.570795
2 0.000000 0.000000 0.000000 -1.570795 -1.570796 0.000000
3 -0.000005 0.000007 3.713255 -0.013781 3.118581 -0.645517
4 18.045723 -0.000002 0.000000 0.000000 -0.000000 -0.635464
5 17.597597 -0.000001 -0.000000 0.001139 0.026796 0.138399
6 3.793089 6.407221 -0.000000 -0.000000 -0.000000 1.570796
7 0.935740 -0.000001 0.000000 0.000000 0.000000 0.000000
8 0.935741 0.000000 0.000000 0.000000 0.000000 0.000000
9 0.935740 0.000000 0.000000 -0.000000 -0.000000 3.141593
10 0.000005 -0.000004 -3.713255 -0.006928 -3.125482 0.237251
11 18.045723 -0.000000 0.000000 -0.000000 0.000000 -1.270162
12 17.597597 0.000000 -0.000000 0.016007 0.007169 -0.315530
13 3.793090 6.407221 -0.000000 -0.000000 0.000000 1.570796

and continues, and so on, and so forth... so, the stuff listed beside "0" is apparently the movement for 3 is apparently the stuff for the biped''s left leg. This pattern continues to the end of the file, where it''s terminated with an end...

end

And that''s the whole format... As far as what those numbers do, the first three are the location of the bone, you can see that clearly because this animation example I''ve given is for walk, in which the half life model walks towards the camera. Notice that Bip01(0)''s Z distance decreases between time 1 and time 2, it continues to do so for the entire file. The next three number *could* be the rotation, ... I''ve noticed that in the file, the right leg''s 6th number fluctuates, perhaps indicating the front to back motion of a walking leg... well, anyway... that''s pretty much the format, and, having written the ms3d loader yourself already, I''m sure you can make more sense of it than I can... I have tons of SMDs if you''d like to work with some, or if you''d like me to send them.

Think that''s enough, and if so, how long will it take you to make an importer?

Thanks,
JudgeX
mrh8red@home.com


Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by JudgeX

The first option I came up with was to fill a model with about 300 frames using different imported SMD files from half-life (and creating my own using the 3dsMAX SMD exporter). Of course, then, I''d need a way to use Bret''s awesome code to play the animation from frame x to frame y on command, which seems really difficult (I don''t think there''s an easy way to throw in a couple of paramaters on the existing functions or anything, it looks like almost a whole rework of the animation portion of the loading code).

[End Quote]

hi all .. ye old anonomous poster again ;D spose i should register sometime heheh .. anyway..

I alterd the advance Animation function to try to play from
frame x to y
the only changes i made really was to that very first part that checks the time .. cause i figured were interpolating between the frames x / y depending on the timers time..
this "seems" to be working for me .. tell me what you think

oh i added a few variables and m_totalFrames, and m_FPS.. those just get set when your loading in the model ..
(in the load model data function)
// skip currentTime
pPtr += sizeof( float );

int totalFrames = *( int* )pPtr;
pPtr += sizeof( int );

m_totalFrames = totalFrames;// <-- add this..
m_FPS = animFPS; // <-- add this..
m_totalTime = (totalFrames*1000.0)/animFPS;

m_numJoints = *( word* )pPtr;
pPtr += sizeof( word );

(then in the advance animation function)
void Model::advanceAnimation(int startframe, int endframe)
{
double time = m_pTimer->getTime();
double endTime; //<-- added

time +=(((startframe)*1000)/m_FPS); // <-- added

if ((endframe > 0) && (endframe < m_totalFrames))//<-add
endTime = (((endframe)*1000)/m_FPS);//<-add
else //<-add
endTime = m_totalTime;//<-add

if ( time > endTime) //<-altered
{
if ( m_looping )
{
restart();
time = (((startframe)*1000)/m_FPS);//<-altered
}
else
time = endTime; //<-altered

}

tell me what you think .. any suggestions would be greatly appreciatied.. *bows down before brett porters wicked interpolation routeens. damn fine code

Share this post


Link to post
Share on other sites
Where did you put m_totalFrames and m_FPS''s declarations?

The code looks good and workable, but I dunno where to put the declarations for these... it looks like you reference them both in Model::advanceAnimation and MilkshapeModel:loadModelData, but I can''t seem to find an appropriate place that lets me compile with the current code...

Thanks,
JudgeX

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
ah, i''ve made a model class inside my engine which i peiced together from the tutorials (this was a big pain hehe took me 3 trys .. when it came to the actual bone animation part with the timers and such .. just took me a bit to figure out how it was all linking together), the vars are just declared in the header file as private doubles.

Share this post


Link to post
Share on other sites
Excellent, got it... works like a charm. Thank you...

Now I''ve just gotta get it to play once and stop .

JudgeX

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
*cry .. i thought it was werking too ..
got an assert failure when i played frames 50-59 for some reason =(

i think its just out to get meh =/

any ideas?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
ya, think i kinda have an idea whats causing it ..
i think its because i''m flipping between the animation sequences real fast without doing that restart().. hmmm.. this is driving me nuts heheh

Share this post


Link to post
Share on other sites
Well, now I have the same problem... I can make it start up and play any sequence of frames I''d like it to, such as start at frame 30, play to frame 70... works awesome... but if I try to change which frames are playing by calling a new advanceanimation with two new numbers as params, it breaks really bad.

Any ideas?

JudgeX

Share this post


Link to post
Share on other sites
muha finaly registerd
.. still havnt really played with it since i''ve had those problems been pretty buissy with werk n such.

you have any thoughts on how we can acomplish this brett?
or what could be causing the assertion failure
(the failures on the interpolation > 0 && <1 line ..)


Share this post


Link to post
Share on other sites
Got a solution for ya... well, it works for me anyway.

make sure you perform a pModel->restart(); after you change the frames every time. There''s no need to do an advanceAnimation(unless you are trying to manually go frame by frame, which I''m not sure is necessary in that manner since you could just make something to quickly swap between the frames you are cycling),

I don''t think... at least, the way I''m doing it, it runs from frame 1 to frame whatever, and then I can run a second animation from frame whatever to frame whatever else, and go back to my original animation at any time.

here''s a sample of my code (I use a very strange coding style, so here goes)

I whipped this up real quick, and just threw it all in NeHeCode.cpp to test, so, it''s rough and nasty, but it works for switching between animation sequences... still haven''t figured out how to get it to play an animation one time and quit, though, which I really need to know how to do now.

first, a couple defines:
(if you''ve ever read an Andre Lamothe book, you might recognize these guys)


#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

and couple variables, idle and moving, both bool



pModel->startframe = 50;
pModel->endframe = 59;

if (moving == FALSE)
{
pModel->startframe = 29;
pModel->endframe = 67;
if (idle == FALSE)
pModel->restart();
idle = TRUE;
}

if ((KEY_DOWN(87)) || (KEY_DOWN(119)))
{
pModel->startframe = 1;
pModel->endframe = 26;
if (moving == FALSE)
pModel->restart();
moving = TRUE;
idle = FALSE;
}
else
moving = FALSE;


Now, when you load this, holding the w key down will play fames 1 - 26, and when you release it, it will play another anim...

Tell me if this helps.

Share this post


Link to post
Share on other sites
quote:
Original post by statix
muha finaly registerd
.. still havnt really played with it since i''ve had those problems been pretty buissy with werk n such.

you have any thoughts on how we can acomplish this brett?
or what could be causing the assertion failure
(the failures on the interpolation > 0 && <1 line ..)





Because you are going past the end of the animation (interp value > 1 )

To be honest I''m not a fan of this method - its come about from a limitation in MS3D but I Think it''d be better to get multiple animations distinctly in a mile. I''ll let you know how the SMD stuff progresses.

~~~
Cheers!
Brett Porter
PortaLib3D : A portable 3D game/demo libary for OpenGL

Share this post


Link to post
Share on other sites
was my hodge-podge description good enough for the SMD files? If not, I can search for more detailed information for you.

Also, I thought of another thing... when you import the SMD files into the milkshape file, it apparently applies certain motions for the bones to go through... so... you could make a master ms3d file that''s just a skeleton, and simply apply all the animations to it, and then inside the code just keep all the movement routines loaded from the initial milkshape file, and then apply those as needed by frame numbers to any other models...

this would be a hybrid of the two methods, and would make it so the models would not be so large (200 - 300 frame models are a bit hard on memory), so it''d be nice to have 1 900 frame animation model and apply your 1 frame models with their skeletons to the skeleton in memory that''s doing the 900 frames.

I almost lost myself on that one, lemme know if it makes sense, or if the SMD idea is better, please.

And thanks again for looking into this, as, I''m not a big fan of the current method myself (I''m just doing what I can, and learning a lot from the experience).

Thanks,
JudgeX
mrh8red@home.com

Share this post


Link to post
Share on other sites
cool .. ya i thought i tried something along those lines .. i''ll give that a try (using your method) when i get home from werk tonight. i''ll let u know how it goes
thanks guys

week people discuss people
average people discuss events
geniouses discuss ideas

Share this post


Link to post
Share on other sites
*jams his tumbs into his eyes
k i''m still having some major problems .. tried for many hours to get this werking and i cant figure out what the problem is.
i set up a few text fields that dump the info to the screen so i can see whats happening .. but i cant understand why its happening...

how could i possibly be getting that assertion failure for the interpolation if i''ve clamped the time down between 0 and m_totalTime.

my model just goes all whacky when i try to play that segment of my animation .. or anysegment really that has a start frame above 3 heh =/



Share this post


Link to post
Share on other sites
When I was fixing mine, I ran into problems along the same lines... the animation spinning and flailing about quickly.

A couple other changes I made were I changed a few of those private functions to public ones... don''t remember which ones... did you try doing the same thing I did, as I listed above? I really couldn''t find any other way of doing it, but that works perfectly for me.

Thanks,
JudgeX

Share this post


Link to post
Share on other sites
ya.. because i was trying to dump lots of different vars to the screen i had to make alot of funtions public .. that shouldnt change much really tho..

i think i''m just going to try that method of useing different bone animation sequences dependin on what ur doin, instead of tryin to put them all into one .. since i can play it through full and loop a single sequence noproblem .. just changing which i''m playing shouldnt be that much different.

remains to be seen tho .. i''ll let ya know

Share this post


Link to post
Share on other sites
I would like to do a little work on that myself, but I don''t really know exactly how it should be done... if anyone could offer any input on how to get started, I''d try to do the loading of different sequences myself. But, as is, I''m pretty much boggled.


Thanks,
JudgeX

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi! I''m coding a simple engine that import ms3d with support for multiple animation (with an invented file format for animation, geometry of objects and skeleton).
My problems are:
1)I think there is a bug in the last Milkshape 3D because it crash when you play an animation with 0 number of rotation or translation keyframes.
2)I''m not sure of this, in the advance animation code of Portalib there is:
frame = pJoint->m_currentRotationKeyframe;
while ( frame < pJoint->m_numRotationKeyframes && pJoint->m_pRotationKeyframes[frame].m_time < time )
{
frame++;
}
pJoint->m_currentRotationKeyframe = frame;

if ( frame == 0 )
transform.setRotationRadians( pJoint->m_pRotationKeyframes[0].m_parameter );
else if ( frame == pJoint->m_numRotationKeyframes )
transform.setRotationRadians( pJoint->m_pRotationKeyframes[frame-1].m_parameter );
else
{
assert( frame > 0 && frame < pJoint->m_numTranslationKeyframes );


In the assert why you use m_numTranslationKeyframes instead of m_numRotationKeyframes? It is a Bug?
i''ve used m_numRot... in my code and it work now (instead with m_numTrans... and 0 number of rotation keyframes it crash...yes like MilkShape3d!!).

-Thx

sorry not a true reply but my account don''t work now!


Simionato Paolo

Share this post


Link to post
Share on other sites
wooo hooo :D
its werkin for me (just the part plaing animation sequences from start frame - end frame) finaly!!! :D :D :D

what i changed was this.. firstly that rotation assertion that was using the translation frames instead which really shouldnt change anything as its just error checking ..

then after the interpolation lines where vars timeDelta and interpvalue are i clamped that so if it was below 0 or above 1 it would be equal to the number closest to it ..
(which really i did so i could see what was hapeining in memory to my model)

then EVERY time i call my advance animation function i call reset
*but i took the
m_pTimer->reset(); line out of there and just added it to my if statement watching if i''d passed the end of my animation time.. works like a charm at the moment :D meh so happy wooo!!!

Share this post


Link to post
Share on other sites
Glad you got that working. Do you know how to stop the animation at a given frame?

Also, I wonder how Mr. Porter is coming along with the SMD importer...

JudgeX

Share this post


Link to post
Share on other sites