Notifications
Clear all

[Closed] Biped Scale

 MZ1

Lets say we have a scene like this:

  • a simple biped with height = 100
  • a teapot linked to the biped head
    if I multiply biped height by 2, the teapot wouldn’t be scaled accordingly. I’m not sure how objects linked to biped inherit scale. My question is how we can build new transformation matrix for the teapot that solve this?
13 Replies

no way … it’s pretty much the same as linking an object to a Point object and changing the object’s ‘size’ property.

the child inherits its parent’s scale only if the parent has ‘anim scale controlling’ any way.

 MZ1

I want to create a tool for scaling biped rigs. For biped parts, it can be done with the bipeds height. Changing height will effect linked objects some how, In case we have control over all scaling behavior, how we can tweak linked objects transform to act like the normal scaling? may code may show the question better:

try(DestroyDialog BipedScalerRol)catch()
rollout BipedScalerRol "Biped Scaler" width:200
(
	local bipCOMController
	local footstepController
	local lastFigureMode
	local canScale = false
	local linkedObjs
	local bipHeight
	
	group ""
	(
		pickButton 'btn_PickBiped' "Pick Biped" align:#center autoDisplay:true width:150
		spinner 'spn_Height' "Height:" align:#left range:[1,1000,1]
	)
	
	fn IsBiped obj =
	(
		classof obj == Biped_Object or classof obj.controller == BipSlave_Control
	)
	
	fn FindDependencies obj objs =
	(
		for o in objects where finditem objs o == 0 and
		(
			refs.DependencyLoopTest obj o or refs.DependencyLoopTest o obj 
		)
		do
		(
			appendifunique objs o
			FindDependencies o objs
		)
	)
	
	on btn_PickBiped picked obj do
	(
		objs = #()
		FindDependencies obj objs
		bipObj = undefined
		for o in objs where IsBiped o while bipObj == undefined do bipObj = o
		if isValidNode bipObj then
		(
			bipCOMObj = biped.getNode bipObj #vertical
			bipCOMController = bipCOMObj.controller
			footstepObj = biped.getNode bipObj #footprints
			footstepObjController = footstepObj.controller
			spn_Height.value = bipHeight = bipCOMController.height
		)
		else
		(
			footstepController = bipCOMController = undefined
		)
		linkedObjs = for o in objs where not IsBiped o and isValidNode (parentObj = o.parent) and IsBiped parentObj collect o
	)
	
	on spn_Height buttondown do
	(
		if bipCOMController != undefined do
		(
			max create mode
			lastFigureMode = bipCOMController.figureMode
			bipCOMController.figureMode = true
			spn_Height.value = bipHeight = bipCOMController.height
			canScale = true
		)
	)
	
	on spn_Height changed val do
	(
		if canScale == true do
		(
			bipCOMController.height = val
			scaleFactor = val / bipHeight
			for i = 1 to linkedObjs.count do
			(
				/* 	
					Question: What I can do here to correct scale of the linked objects?
				*/
			)
		)
	)
	
	on spn_Height buttonup do
	(
		if bipCOMController != undefined do
		(
			canScale = false
			bipCOMController.figureMode = lastFigureMode
		)
	)
)
CreateDialog BipedScalerRol

well… maybe something like this:

b = $bip001
(
	d = dummy boxsize:([1,1,1] * b.controller.height / 10) transform:b.transform parent:b
	s = d.scale.controller = scale_script()
	s.addconstant "sc_origin" b.controller.height
	s.addobject "sc_current" b.controller
	s.setexpression "[1,1,1] * sc_current.height/sc_origin"
)

but “height” property is not a subanim (cannot be animated). It’s a Biped Structure parameter, and available in Figure editing mode only.

 MZ1

Yea! then we can link max objects to that dummy right? it works like a bridge to correct scale.

 MZ1

is it possible to scale the rig without adding that dummy? just by multiplying transformation? Because I want to scale existing rigs without adding new objects.

I hope you don’t want to animate Biped scale.

So, scale with dummy, reset XForm and delete the dummy.

2 Replies
 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

Not in this case, but it is not possible with callbacks and update at time change?

Why reset XForm?

(@denist)
Joined: 11 months ago

Posts: 0

my bad… you need to reset Scale only. Other way all children inherit scale from the ‘dummy’, and you cannot delete it.

 MZ1

No need to reset anything, I just insert the dummy between linked objects and biped. Then I will link them back again. Then I will delete dummies:

try(DestroyDialog BipedScalerRol)catch()
rollout BipedScalerRol "Biped Scaler"
(
	local bipCOM
	local bipCOMController
	local allObjs = #()
	local dummies = #()
	local canScale = false
	local lastFigureMode
	local skinModifiers = #()
	local counter = 0
	
	fn IsBiped obj =
	(
		classof obj == Biped_Object or classof obj.controller == BipSlave_Control
	)
	
	fn GetSkin obj =
	(
		skinMod = undefined
		for m in obj.modifiers where classof m == skin do skinMod = m
		skinMod
	)
	
	fn FindDependencies obj objs = if isvalidnode obj do
	(
		progressUpdate (counter += .1)
		for o in objects where isvalidnode obj and finditem objs o == 0 and
		(
			refs.DependencyLoopTest obj o or refs.DependencyLoopTest o obj 
		)
		do
		(
			appendifunique objs o
			FindDependencies o objs
		)
	)
	
	group ""
	(
		pickButton 'btn_PickBiped' "Pick Biped" align:#center autoDisplay:true width:150 filter:IsBiped
		spinner 'spn_Height' "Height:" align:#left range:[1,1e+09,1] enabled:false
	)
	
	fn FnSpnButtonDown =
	(
		if isValidNode bipCOM do
		(
			for o in allObjs where isValidNode o collect o
			flagForeground allObjs true
			max create mode
			lastFigureMode = bipCOMController.figureMode
			bipCOMController.figureMode = true
			bipHeight = bipCOMController.height
			dummies = for o in allObjs where isvalidnode o and not IsBiped o and isValidNode (parentObj = o.parent) and IsBiped parentObj collect
			(
				d = dummy boxsize:([1,1,1] * bipHeight / 10) transform:parentObj.transform parent:parentObj ishidden:true
				s = d.scale.controller = scale_script()
				s.addconstant "sc_origin" bipHeight
				s.addobject "sc_current" bipCOMController
				s.setexpression "[1,1,1] * sc_current.height/sc_origin"
				o.parent = d
				d.parent = parentObj
				d
			)
			skinModifiers = for o in allObjs where isValidNode o and superclassof o == GeometryClass and (skinMod = GetSkin o) != undefined collect
			(
				skinMod.always_deform = false
				skinMod
			)
			canScale = true
		)
	)
	
	fn FnSpnChanged val:spn_Height.value =
	(
		if canScale == true do
		(
			bipCOMController.height = val
		)
	)
	
	fn FnSpnButtonUp =
	(
		if canScale == true do
		(
			for o in dummies where isValidNode o do o.children.parent = o.parent
			delete dummies
			for skinMod in skinModifiers do skinMod.always_deform = true
			bipCOMController.figureMode = lastFigureMode
			canScale = false
			flagForeground allObjs false
		)	
	)
	
	on btn_PickBiped picked bipObj do
	(
		progressStart "Finding objects..."
		bipCOM = bipObj.controller.rootNode
		bipCOMController = bipCOM.controller
		allObjs = #()
		FindDependencies bipCOM allObjs
		spn_Height.value = bipHeight = bipCOMController.height
		spn_Height.enabled = true
		progressEnd()
	)
	
	on spn_Height buttondown do
	(
		FnSpnButtonDown()
	)
	
	on spn_Height changed val do
	(
		FnSpnChanged val:val
	)
	
	on spn_Height buttonup do
	(
		FnSpnButtonUp()
	)
	
	on spn_Height entered inSpin_arg inCancel_arg do
	(
		if inSpin_arg == false do
		(
			FnSpnButtonDown()
			FnSpnChanged()
			FnSpnButtonUp()
		)
	)
)
CreateDialog BipedScalerRol

Excellent! I’m glad it works

but… if this is a one-time scaling, then there is no need to bind the dummy through the script controller. Just use default scale controller and set it’s value the same way as I do it for the scale script.

2 Replies
 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

Then we should add it to the spinner changed event, Which I’m not sure it is faster this way…

 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

It would be next phase to make it permanent, but I think we should first solve height subanim. I will do some tests on that…

 MZ1

This is my first try to make animatable height:

(
	customAttribute = attributes CustomParameters
	(
		parameters Param_Main rollout:Rol_Main
		(
			BipCOMMonitor type:#maxobject
			Height type:#float ui:Height default:10
			on Height set val do this.UpdateHeight()
		)
		 
		rollout Rol_Main "Parameters"
		(
			spinner Height "Height" type:#float range:[1,1e+09,100]
		)
		
		fn UpdateHeight =
		(
			if Height > 0 and classof BipCOMMonitor == NodeMonitor do
			(
				if isvalidnode (BipCOM = BipCOMMonitor.node) then
				(
					bipCOMController = BipCOM.controller
					with redraw off
					(
						bipCOMController.figureMode = true
						bipCOMController.Height = Height
						bipCOMController.figureMode = false
					)
				)
				else
				(
					unregisterTimeCallback UpdateHeight
				)	
			)
		)
		
		fn AddTimeCallback =
		(
			registerTimeCallback UpdateHeight
		)
		
		on postCreate do
		(
			AddTimeCallback()
		)
		
		on postLoad do
		(
			AddTimeCallback()
		)
	)
	
	bipCOM = $Bip001
	CustAttributes.add bipCOM customAttribute
	customAttribute = custAttributes.get bipCOM customAttribute
	customAttribute.Height = bipCOM.controller.height
	customAttribute.BipCOMMonitor = NodeMonitor node:bipCOM
)