MAXScript Biped Auto Rigger

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

REPLY TO THREAD
 
Thread Tools Search this Thread Display Modes
Old 05 May 2014   #16
Hello,

Sorry for the really late reply, I did a test with maxObjectTab and referencing a global object, is this what you meant:
(	
	local ikArray = #(), fkArray = #()

	delete objects
	
	function createBone startPos endPos zAxis sideFins frontFin backFin boneName boneColor boneArray boneParent:undefined =
	(
		theBone = boneSys.createBone startPos endPos zAxis
		theBone.width = 3
		theBone.height = 3
		theBone.sideFins = sideFins
		theBone.frontFin = frontFin
		theBone.backFin = backFin
		theBone.name = boneName
		theBone.parent = boneParent
		theBone.wireColor = boneColor
		append boneArray theBone
	)
	
	theRoot = point centerMarker:false axisTripod:false cross:false box:true size:20 name:(uniqueName "root") wireColor:[6,135,6]
	
	createBone [0,0,0] [30,10,0] [0,0,10] true false false (uniqueName "ik_Bone") [135,6,6] ikArray boneParent:theRoot
	createBone [30,10,0] [60,0,0] [0,0,10] true false false (uniqueName "ik_Bone") [135,6,6] ikArray boneParent:ikArray[ikArray.count]
	createBone [60 ,0,0]  ([60,0,0] + ikArray[2].transform.row1 * 3) [0,0,1] false false false (uniqueName "ik_Bone") [135,6,6] ikArray boneParent:ikArray[ikArray.count]
	
	createBone [0,0,0] [30,10,0] [0,0,10] false true true (uniqueName "fk_Bone") [6,6,135] fkArray boneParent:theRoot
	createBone [30,10,0] [60,0,0] [0,0,10] false true true (uniqueName "fk_Bone") [6,6,135] fkArray boneParent:fkArray[fkArray.count]
	createBone [60 ,0,0]  ([60,0,0] + fkArray[2].transform.row1 * 3) [0,0,1] false false false (uniqueName "fk_Bone") [6,6,135] fkArray boneParent:fkArray[fkArray.count]
	
	theTarget = point centerMarker:false axisTripod:false cross:false box:true size:10 name:(uniqueName "ikT_arget") wireColor:[135,6,6] position:ikArray[2].position
	theTarget.parent = theRoot
	theControl = point centerMarker:false axisTripod:false cross:false box:true size:10 name:(uniqueName "ik_Control") wireColor:[135,6,6] position:ikArray[3].position
	theControl.parent = theRoot
	
	theIK = IKSys.ikChain ikArray[1] ikArray[3] "IKHISolver"
	theIK.name = (uniqueName "ik_Goal")
	theIK.parent = theControl
	theIK.transform.controller.useVHTarget = true
	theIK.transform.controller.VHTarget = theTarget
	
	rootCA = attributes FKIKSnapCA
	(
		parameters FKIKSnapP
		(
			rootTab type:#maxObjectTab tabSizeVariable:on tabSize:0
		)
	)
	
	custAttributes.add theRoot.baseObject rootCA
	append theRoot.baseObject.FKIKSnapCA.rootTab (nodeTransformMonitor node:fkArray[1] forwardTransformChangeMsgs:false) --1
	append theRoot.baseObject.FKIKSnapCA.rootTab (nodeTransformMonitor node:fkArray[2] forwardTransformChangeMsgs:false) --2
	append theRoot.baseObject.FKIKSnapCA.rootTab (nodeTransformMonitor node:fkArray[3] forwardTransformChangeMsgs:false) --3
	append theRoot.baseObject.FKIKSnapCA.rootTab (nodeTransformMonitor node:ikArray[1] forwardTransformChangeMsgs:false) --4
	append theRoot.baseObject.FKIKSnapCA.rootTab (nodeTransformMonitor node:ikArray[2] forwardTransformChangeMsgs:false) --5
	append theRoot.baseObject.FKIKSnapCA.rootTab (nodeTransformMonitor node:theControl forwardTransformChangeMsgs:false) --6
	append theRoot.baseObject.FKIKSnapCA.rootTab (nodeTransformMonitor node:theTarget forwardTransformChangeMsgs:false) --7
	
	controlCA = attributes FKIKSnapCA
	(
		parameters FKIKSnapP rollout:FKIKSnapR
		(
			controlTab type:#maxObjectTab tabSizeVariable:on tabSize:0
		)

		rollout FKIKSnapR "FK-IK Contols"
		(
			button FKIK "Snap FK To IK" width:130 align:#center
			button IKFK "Snap IK To FK" width:130 align:#center
			
			on FKIK pressed do
			(
				controlTab[1].node.baseObject.FKIKSnapCA.rootTab[1].node.transform = controlTab[1].node.baseObject.FKIKSnapCA.rootTab[4].node.transform
				controlTab[1].node.baseObject.FKIKSnapCA.rootTab[2].node.transform = controlTab[1].node.baseObject.FKIKSnapCA.rootTab[5].node.transform
			)
			
			on IKFK pressed do
			(
				controlTab[1].node.baseObject.FKIKSnapCA.rootTab[6].node.transform = controlTab[1].node.baseObject.FKIKSnapCA.rootTab[3].node.transform
				controlTab[1].node.baseObject.FKIKSnapCA.rootTab[7].node.transform = controlTab[1].node.baseObject.FKIKSnapCA.rootTab[2].node.transform
			)
		)
	)
	
	addModifier theControl (EmptyModifier())
	custAttributes.add theControl.modifiers[1] controlCA
	append theControl.modifiers[1].FKIKSnapCA.controlTab (nodeTransformMonitor node:theRoot forwardTransformChangeMsgs:false)
		
	addModifier fkArray[1] (theControl.modifiers[1])
	addModifier fkArray[2] (theControl.modifiers[1])
)

I added the global node to a maxObjectTab parameter stored on the IK control's attribute holder which I then instanced on to the two FK bones so that you don't need to have anything selected; using $ wouldn't work if you pinned the stack the deselected the object.

-Harry
__________________
LinkedIn | Website | Vimeo | YouTube | Twitter | Facebook
 
Old 05 May 2014   #17
Hey Harry,

I made a video to try and show you what I meant. Forgot to say in the video but all the rig data is stored in maxObject parameters on the rig_data definition...

https://drive.google.com/file/d/0BwIHsR2ux1nVWl81NWVldVczdEE/edit?usp=sharing


Hope it helps...

PS sorry for the terrible video quality - still getting the hang of the screen capture software :-)
 
Old 05 May 2014   #18
Thanks a lot for creating the video (I'd suggest an old version of CamStudio with the ffdshow codec for screen capture)!

It seems that we both get the same result. Why do you need the rig data modifier? Why do you use a function to do the snapping? What do you use the dialog window for other than inspecting things like objects parent and what type of control it is?

-Harry
__________________
LinkedIn | Website | Vimeo | YouTube | Twitter | Facebook
 
Old 05 May 2014   #19
Thanks for the tip - I'll look into getting an older version of Camstudio...

It's funny how you think there are good reasons for doing stuff until someone asks you to explain / justify them!! Here goes:

Why do you need the rig data modifier?

I use that as a standard storage place for any rig controls - whether they have snapping funcionality or not. It doesn't need to be on a seperate modifier, I just find it easier to have that seperation.

Why do you use a function to do the snapping?

This makes it easier to handle special cases and exceptions. In the video all the examples are very simple - matching one transform to another. However, with something like a reverse foot you may also need to zero out certain attributes (roll, toeTap etc...) before doing the snap. Encapsulating that in a centralized function means you can use the exact same code in each control to call the function but the results are tailored based on that control's own rig_data. I do a lot of python scripting in Maya and really like classes for their object oriented properties - this is what I'm trying to replicate to a certain extent in Max. Each control has a set of properties which it supplies as arguments to a centralised set of functions. It then becomes trivial to add new functions to extend functionality - I use the same rig_data when calling pose functions (copy, paste, mirror etc.) and to specify whether to apply the results to the whole rig, just the one rig module (arm / leg etc) or just that single ctrl.

What do you use the dialog window for other than inspecting things like objects parent and what type of control it is?

I use that dialog to initially set all the rig_data for each control - it's just a friendlier way of adding / editing the weak referencing in the rig_data custom attributes. It handles lots of stuff internally like, whenever you specifiy a control's parent, it also appends the control to the parent control's 'children' maxObjectTab. (And removes it if a different parent is subsequently picked). It's very easy to lose track of that stuff on a rig with lots of controls.

OK I'm sick of typing - here's another quick video!!
 
Old 05 May 2014   #20
Thanks for the video again!

Ok, so the RIG_DATA modifier holds custom attributes and necessary object transform information in an maxObjectTab which are passed to the root control to be used in a function? I didn't realise you could store custom attributes in maxObjectTab's or are you just referencing them from a stored node?

I imagine, for example, the IK->FK and FK->IK functions are the same functions which are used by all the limbs?

You mention adding new functions to the root control at 3:50 is that achieved just by updating the custom attribute definition on the root control?

Thanks again,
-Harry
__________________
LinkedIn | Website | Vimeo | YouTube | Twitter | Facebook
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 12:58 AM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.