[Closed] Biped Scale
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?
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.
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.
Yea! then we can link max objects to that dummy right? it works like a bridge to correct scale.
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.
Not in this case, but it is not possible with callbacks and update at time change?
Why reset XForm?
my bad… you need to reset Scale only. Other way all children inherit scale from the ‘dummy’, and you cannot delete it.
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.
Then we should add it to the spinner changed event, Which I’m not sure it is faster this way…
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…
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
)