[Closed] Seamless IK to FK problem
Hey everyone.
I have this script I’m working on that allows to seamlessly go from IK to FK on a bone chain. I have an IK chain of bones and a FK chain. The IK chain should be the one skinned on the mesh. Whe you animate either the IK or FK chain, the other chain is supposed to update itself as you transform the selected chain. The thing is that it does update itself… but only on the X axis. It does follow other axis, but not in realtime. Also, this problem occurs on both chains of bones, so I really don’t know whats going on here.
Here’s my code.
test = ATTRIBUTES whenTest
(
FN applyRot =
(
--$ikTest.position = $FK_Hand.position
--$ikTest.rotation = $FK_Hand.rotation
$Arm.transform.controller.FK_Sub_Control.rotation.controller.Xrotation = $FK_Arm.rotation.controller.Xrotation
$Arm.transform.controller.FK_Sub_Control.rotation.controller.Yrotation = $FK_Arm.rotation.controller.Yrotation
$Arm.transform.controller.FK_Sub_Control.rotation.controller.Zrotation = $FK_Arm.rotation.controller.Zrotation
$ForeArm.transform.controller.FK_Sub_Control.rotation.controller.Xrotation = $FK_ForeArm.rotation.controller.Xrotation
$ForeArm.transform.controller.FK_Sub_Control.rotation.controller.Yrotation = $FK_ForeArm.rotation.controller.Yrotation
$ForeArm.transform.controller.FK_Sub_Control.rotation.controller.Zrotation = $FK_ForeArm.rotation.controller.Zrotation
$Hand.transform.controller.FK_Sub_Control.rotation.controller.Xrotation = $FK_Hand.rotation.controller.Xrotation
$Hand.transform.controller.FK_Sub_Control.rotation.controller.Yrotation = $FK_Hand.rotation.controller.Yrotation
$Hand.transform.controller.FK_Sub_Control.rotation.controller.Zrotation = $FK_Hand.rotation.controller.Zrotation
$Swivel.position = $Swivel_Pos.position
)
FN applyRotFK =
(
$FK_Arm.rotation.controller.Xrotation = $Arm.transform.controller.FK_Sub_Control.rotation.controller.Xrotation
$FK_Arm.rotation.controller.Yrotation = $Arm.transform.controller.FK_Sub_Control.rotation.controller.Yrotation
$FK_Arm.rotation.controller.Zrotation = $Arm.transform.controller.FK_Sub_Control.rotation.controller.Zrotation
$FK_ForeArm.rotation.controller.Xrotation = $ForeArm.transform.controller.FK_Sub_Control.rotation.controller.Xrotation
$FK_ForeArm.rotation.controller.Yrotation = $ForeArm.transform.controller.FK_Sub_Control.rotation.controller.Yrotation
$FK_ForeArm.rotation.controller.Zrotation = $ForeArm.transform.controller.FK_Sub_Control.rotation.controller.Zrotation
$FK_Hand.rotation.controller.Xrotation = $Hand.transform.controller.FK_Sub_Control.rotation.controller.Xrotation
$FK_Hand.rotation.controller.Yrotation = $Hand.transform.controller.FK_Sub_Control.rotation.controller.Yrotation
$FK_Hand.rotation.controller.Zrotation = $Hand.transform.controller.FK_Sub_Control.rotation.controller.Zrotation
)
FN selectchange =
(
IF $FK_ForeArm.isSelected == true THEN
(
deleteAllChangeHandlers id:#fkTest
when transform $ikTest changes id:#ikTest do
(
IF $ikTest.transform.controller.enabled == 1 THEN
(
applyRotFK()
)
ELSE
(
$ikTest.transform.controller.enabled = 1
)
)
)
IF $FK_Arm.isSelected == true THEN
(
deleteAllChangeHandlers id:#ikTest
when transform $FK_Arm changes id:#fkTest do
(
IF $ikTest.transform.controller.enabled == 0 THEN
(
applyRot()
)
ELSE
(
$ikTest.transform.controller.enabled = 0
)
)
)
IF $FK_ForeArm.isSelected == true THEN
(
deleteAllChangeHandlers id:#ikTest
when transform $FK_Arm changes id:#fkTest do
(
IF $ikTest.transform.controller.enabled == 0 THEN
(
applyRot()
)
ELSE
(
$ikTest.transform.controller.enabled = 0
)
)
)
)
)
custAttributes.add $.modifiers[1] test
-- callbacks.addScript #selectionSetChanged "$ikTest.modifiers[1].selectchange()" id:#testSelectionSetMonitor persistent:true
I’d upload the scene, but I’m not allowed to do so at work. Any idea if the problem comes from my code or simply from max?
I think you are going to find there are far more issues with what you are trying to do then what you are asking about here. It just isn’t a good way to go about it in production.
First off you shouldn’t be listing objecfs by name and second as soon as you scrub the animation it will key every frame.
I’ve been working a bit more on my code now and my last problem has been solved. Just one last thing to figure out and it’s all going to be good.
What do you mean by “listing objects by name”? Is there another way to acces an object other than by it’s name? Also it doesn’t key every frame when I scrub through my animation (maybe that’s because of my updated script).
I was able to correct my problem using max 2009’s maxscript reference instead of max 9’s.
test = ATTRIBUTES whenTest
(
FN applyRot =
(
--detect if hand is selected
if $Hand_cntrl.isSelected == true then
(
--delete change handlers
deleteAllChangeHandlers id:#arm
deleteAllChangeHandlers id:#forearm
deleteAllChangeHandlers id:#swivel
--IK change handler
when transform $Hand_cntrl changes id:#hand handleAt:#redrawViews do
(
--check if IK is active
if $ikTest.transform.controller.enabled == 1 then
(
$Arm_cntrl.transform = $Arm_Rot.transform
$ForeArm_cntrl.transform = $ForeArm_Rot.transform
)
else
(
$ikTest.transform.controller.enabled = 1
)
)
)
--detect if swivel is selected
if $Swivel.isSelected == true then
(
--delete change handlers
deleteAllChangeHandlers id:#hand
deleteAllChangeHandlers id:#arm
deleteAllChangeHandlers id:#forearm
--IK change handler
when transform $Swivel changes id:#swivel handleAt:#redrawViews do
(
--check if IK is active
if $ikTest.transform.controller.enabled == 1 then
(
$Arm_cntrl.transform = $Arm_Rot.transform
$ForeArm_cntrl.transform = $ForeArm_Rot.transform
)
else
(
$ikTest.transform.controller.enabled = 1
)
)
)
--detect if arm is selected
if $Arm_cntrl.isSelected == true then
(
--delete change handlers
deleteAllChangeHandlers id:#hand
deleteAllChangeHandlers id:#forearm
deleteAllChangeHandlers id:#swivel
--arm change handler
when transform $Arm_cntrl changes id:#arm handleAt:#redrawViews do
(
--check if IK is active
if $ikTest.transform.controller.enabled == 1 then
(
$ikTest.transform.controller.enabled = 0
)
$Hand_cntrl.transform = $Hand_Rot.transform
$Swivel.pos = $Swivel_Pos.pos
)
)
--detect if forearm is selected
if $ForeArm_cntrl.isSelected == true then
(
--delete change handlers
deleteAllChangeHandlers id:#hand
deleteAllChangeHandlers id:#arm
deleteAllChangeHandlers id:#swivel
--arm change handler
when transform $ForeArm_cntrl changes id:#forearm handleAt:#redrawViews do
(
if $ikTest.transform.controller.enabled == 0 then
(
$ikTest.transform.controller.enabled = 0
)
$Hand_cntrl.transform = $Hand_Rot.transform
$Swivel.pos = $Swivel_Pos.pos
)
)
)
)
custAttributes.add $.modifiers[1] test
-- callbacks.addScript #selectionSetChanged "$ikTest.modifiers[1].applyRot()" id:#testSelectionSetMonitor persistent:true
I’m really curious though on how you can interact with objects without using their names. I was taught to use the object’s name. Not that I had a really advanced maxscript course at school mind you… I’m really just a beginner in maxscript.
Basically you never want to be in a position for tools like this where you list an object by name. As soon as you rename something it will break and it is slower since Max has to continually search the scene for the correct objects to work with. What if there are duplicate names as well. So what you want in the parameter block of the CA Def are maxObject type parameters that hold a weak reference to the nodes you are going to work with using nodeTransformMonitor.
Interesting. I’ll have to read on that. Is the maxscript reference file good enough to give me a good starting point on this?
Thanks a bunch for your help.
I guess you will have to find out. Information on my site about it as well.
Hmm well let’s just say the information about it in the maxscript reference file is sparse at best… No example whatsoever. I’ll go check it on your site, thanks.
Hi Pierre,
one of the most common things that people say about the help is that it is sparse – In truth there is more than enough information, it’s mainly knowing where to look, partly due to the fact that things may be under terms that you haven’t encountered yet. In this case, it shouldn’t be hard, the creating functions topic holds information about what paul was talking about. – you need to pass the selected node as an argument rather than hard coding it into the function. that way you can reuse it with different situations. Having a hardcoded function set out like this is not using it to it’s fullest.
Well, I have to agree that the help file is mostly quite adequate and my first resource for information. The info about the NodeTransformMonitor and RefTargMonitorRefMaker are really just 1 page with the properties and a description. Since this is really a important topic for riggers, I don’t understand that there’s not even a single example about the use of the weak referencing in combination with a CA. But other then that the manual mostly fills my info needs!
-Johan
In general the helpfile in max9 is great, in 2009 it’s even better. But there are some topics that are lacking info. And unfortunatly, it seems these topics are often important for my work so sometimes I have to turn to the magic of the internet. Still even the internet doesn’t have all the answers I need.
For exemple, how do you detect the deletion of a keyframe? There’s no callbacks, no “when” attributes, nothing… at least that I know of. And unfortunatly, the last little bug I have to clear for my script to work the way I want has to do with deleting keyframes…
Well, I’m going back on google!