A tricky controlJoint and blending animation puzzle

Hi, I’m getting a weird issue using controlJoint. I have an actor that has two animations an ‘idle’ and a ‘getkey’. In the ‘idle’ animation the actor’s root joint ‘Fro:BatSkel’ starts at the origin, while in the ‘getkey’ animation his root joint starts at an arbitrary position in model space.

As a result, when I play these animations one after the other or attempt to blend them together the actor’s root joint jumps around because it’s in a different place in each animation.

I would like to use control joint to zero out all transformations on this actor’s root joint so that I can smoothly play these animation one after the other with NO popping.

This solution seems to work EXCEPT on the very first time I play the animations in seqence. On the first iteration, the actor ‘pops’ at the transition point between ‘idle’ and ‘getkey’ to the arbitrary position for a frame and then pops back to zero for the rest of the animation. After the first iteration, everything works fine (no popping when it transitions)

Below is the sample code I’m using that causes this effect w/some more detailed comments.

Please help, I’ve spent WAY too long banging my head over this one.

-Thanks

"""
Load up my actor w/two animations
-The 'idle' animation starts w/the root joint 'Fro:BatSkel' at Vec3(0, 0, 0) in model space
-The 'getkey' animation starts wthe root joint 'Fro:BatSkel' at Vec3(-0.850327, 0.812433, 11.3742) in model space
"""
myActor = Actor("Froderick_Bind",{'idle':'FRO_Idle',
                                                                  'getkey':'FRO_WB_getKey'})
"""
Use controlJoint on the actor's root joint 'Fro:BatSkel' to zero out any transformations applied to it by animations.
The desired effect is that this joint will be pinned to (0,0,0) no matter which animation is playing
"""
myActor.controlJoint(None,'modelRoot','FRO:BatSkel')

myActor.reparentTo(render)

getkey = ActorInterval(myActor,'getkey') #Create an ActorInterval to play getkey
idle = ActorInterval(myActor,'idle') #Create an ActorInterval to play idle

idle2getkey = Sequence(idle,getkey)

"""
On the first iteration of this loop the actor pops to Vec3(-0.850327, 0.812433, 11.3742) for a frame when it gets to the getkey animation is started. The actor then returns to (0,0,0) for the rest of the animation.

On subsequent iterations the animations blend together smoothly w/NO popping

The desired effect is to have no popping of this kind on any of the loop iterations.
The call to 'controlJoint' SHOULD be doing this, but it seems to fail on the first frame of the first iteration.
"""
idle2getkey.loop()

The controlJoint() call will disassociate the joint from its animation and return a handle for you to change the joint position yourself. But if you never change it, it will remain at its original position. Try something like this:

BatSkelJoint = myActor.controlJoint(None,'modelRoot','FRO:BatSkel')
BatSkelJoint.setPos(0, 0, 0)

david

Hi,

I tried your suggestion but w/o much luck. Here’s what I’ve done. I also included a few movies of the issue to help clarify.

...
BatSkelJoint = myActor.controlJoint(None,'modelRoot','FRO:BatSkel')
BatSkelJoint.setPos(0,0,0)
...
idle2getkey = Sequence(idle,getkey)

This seems to work only part of the time. Here’s an example of a run in which the transition looks correct.

http://www.goldengoosegames.com/forumpost/insequence.swf.html

In other runs however, I get the popping on the transition:

http://www.goldengoosegames.com/forumpost/insequence2.swf.html

Next, I tried playing these animations w/a few frames of blending between them for a smoother transition. This problem reared its ugly head again. The issue seems to take place only during the blend and then my actor returns to it’s desired location for the rest of the animation (Notice, I let it loop twice in this one, the second loop doesn’t show any of this behavior, only the first one)

http://www.goldengoosegames.com/forumpost/blended.swf.html

I used this code:

BatSkelJoint = myActor.controlJoint(None,'modelRoot','FRO:BatSkel')
BatSkelJoint.setPos(0,0,0)
myActor.reparentTo(render)

getkey = ActorInterval(myActor,'getkey') #Create an ActorInterval to play getkey
idle = ActorInterval(myActor,'idle') #Create an ActorInterval to play idle

myActor.enableBlend()
myActor.setControlEffect('idle',1.0)
myActor.setControlEffect('getkey',0.0)


blendDuration = (10.0/30.0) #10 Frames of blending
idleToGetKeyBlend = LerpAnimInterval(myActor,blendDuration,'idle','getkey')
getKeyToIdleBlend = LerpAnimInterval(myActor,blendDuration,'getkey','idle')

idle2getkey = Track(
                      #a.) Start the idle
                     (0,idle),
                     #b.) Near the end of the idle blend in getkey
                     ((idle.getDuration()-blendDuration),Parallel(idleToGetKeyBlend,getkey)),
                     #c.) Near the end of getkey blend idle back in for smooth looping
                     ((idle.getDuration()+getkey.getDuration()-2*blendDuration),Parallel(PosInterval(BatSkelJoint,Vec3(0,0,0)),getKeyToIdleBlend,idle))
                    )

If however I switch the order of the animations in the sequence, everything looks fine.

http://www.goldengoosegames.com/forumpost/blendedgetkey2idle.swf.html

Using this code:

getkey2idle = Track(
                      #a.) Start the getkey
                     (0,getkey),
                     #b.) Near the end of the getkey blend in idle
                     ((getkey.getDuration()-blendDuration),Parallel(getKeyToIdleBlend,idle)),
                     #c.) Near the end of idle blend getkey back in for smooth looping
                     ((idle.getDuration()+getkey.getDuration()-2*blendDuration),Parallel(PosInterval(BatSkelJoint,Vec3(0,0,0)),idleToGetKeyBlend,getkey))
                    )

Please HELP!
Thanks again for your consideration
-A