Notifications
Clear all

[Closed] constrain pos to a spherical radius

It seems to work really well. I don’t know how it’ll work for the OP but I learned something from it. Thanks!

I messed around with the change script and came up with this method of constraining the ctrl postion as if it were the bone nub, without setting it to boneEnbaled true

when transform $ctrl changes do( in coordsys parent($ctrl.pos=(normalize $ctrl.pos * $bone.length))) 

(this case, $ctrl.parent shares the pos of $bone)

To keep the constraint across sessions, I built a button function to apply the code to each CTRL / Bone pair, and added it via custom attributes to the root control. The animator enables the change script when they wish.

I thought a script controller could do this, but a position script seems to disable the move manipulator.

I’ll hunt down the thread mentioned and see the folly of my approach

Try to render your animation. Does it render properly?

rendering is irrelevant.
we are exporting to a game engine, all bone transforms get baked in FBX.
CTRL keyframes are saved in XAF files for re-use.

So your animators never need to make an animation preview before exporting to FBX?

Nope, we export and review in the engine.

I posted a similar question at tech-art.org and got a clever solution that avoids change scripts entirely, using a scale script controller on a proxy object.

a late thread bump. The solution linked to above worked quite well.
It basically involved ‘cheating’ with a scale script controller on an unrelated object.
I condensed the solution into a fn that I can pass the bone, ctrl object, and script holding object. It seems to be working quite well.


	fn radiusCtrlLimit theCtrl theBone theHolder=(
		/*
			theCtrl = object you wish to constrain to a radius
			theBone = a bone with w/ rotation lookat constrained to theCtrl, whose length will determine the radius
			theHolder = the object that will hold the script.

			objects and lookat constraints created elsewhere
		*/

		ScriptString= @"if distance bone point != bone_length then
		(
			with animate off
			(
				point.pos = (normalize (point.pos - bone.pos))*bone_length + bone.pos
			)
		)

		[1, 1, 1]"

		sc=scale_script()
		sc.addobject "point" theCtrl
		sc.addobject "bone" theBone
		sc.addconstant "bone_length" theBone.length
		sc.script=scriptString
		theHolder.scale.controller=sc
	),

as i said earlier i’m not a fan of this type of rig but everything could be done much easier


delete objects
s = geosphere radius:20
d = dummy boxsize:[10,10,10] pos:[s.radius,0,0]

p = d.pos.controller = position_list()
p.weight[1] = 0

sc = p.available.controller = position_script()
sc.addtarget "radius" s.baseobject[#radius]	
sc.addobject "pos" p[1]
sc.setexpression "(normalize pos.value)*radius"

/* it's optional... if you want to constraint dummy to the sphere position */
d = p.available.controller = s.pos.controller

sc.addobject "pos" p[1]

So instead of a third object to hold a hacked script, you are using a position_list
adding the position script d.pos.controller[2], and
passing the value of d.pos.controller1 to the script?

very clever, and simple. It is not obvious at all that this was possible, though I guess it makes sense.

Page 2 / 4