Can impossible be possible? (The real challenge)


i’ve given a clue… my solution is based on list controllers where some of their sub controllers are scripted.
(ps. the weak reference is a myth)


Thanks for the link, :slight_smile: - the post was actually in response to what Maulik was trying to do - namely multi-directional constraints.

I basically first started with a single one directional system - single object, multiple targets. This is pretty simple - if i have object A and object B, you store A’s transform relative to B. Then A assumes B’s transform space relative to A’s coordinate space. (remember if A has a parent you getting it relative to its parent) Then adding the stored transform back. Its really very simple.

What I found tricky was having A follow B and vice versa i.e multi-directional-ness - so basically I use the forward transform monitor to push transform updates but not have a direct reference. What is hard making it friendly for the user.

What i can tell you is mixing up both methods, i.e having one child, lots of parents (single direction), and lots of children one parent (multi-direction) causes lots of pain, in terms of evaluation order - don’t try it.


Im not sure i follow you in saying the weak reference is a myth, do you mean functionality or the fact that node assignment in script controllers use it automatically - therefore you don’t have to strictly define it. I like the fact i can push transform changes to an object without needing a direct link to it. Or do you mean for this problem?

As to the problem in question, you could do something like this:

Two objects: A, B

Instance the rotation controller between the two
Give both a position list controller, with two bezier_position controllers in each.
Instance the first position controller between the two.
On the second create a script controller with something like this:

*Rot is the instance rotation controller between the two
For A - (transMatrix [0,0,100] * rot.value).pos
For B - (transMatrix [0,0,-100] * rot.value).pos

Your going to have to handle the the switch, by keying the second controllers weight and shift the switched weights object position back. Basically your keying the offset. But all doable.


that’s exactly what i said above.
i will believe anyone who say “i’ve solved that!”. great! you don’t have to show and prove it. good for you.
but i don’t see anyone who is close to a solving.

weak reference…
there is a very old code in max sdk that checks the dependency loop. and the checking is wrong!
there are many situations where the system ‘locks’ some connection (wiring, referencing, etc.) because of a ‘fake’ dependency loop.
i think that nodemonitor and nodetransformmonitor classes were specially designed to just fool and only fool the system. these classes do only ‘not sending’ some messages to the system making the system ‘not check’ dependency loop. it’s just only a trick and not a solution.


Do you mean the issue of offset? Or just the problem itself?


i mean that i didn’t see yet any idea that works. i didn’t see THE KEY to make me believe that the idea works.


Well just throwing ideas out there - i’m not near max but here goes using just my brain. We could do something like this:

3 nodes A, B, C
B instanced rotation onto A, C
A, C position list controller with two bezier_positions controllers
Instance B’s position controller on to A, C’s first bezier_position controller
A script controller on A/C’s second bezier position controller

Edit: this is less of an orbit around each other, more of an orbit around the center.


hmmm… sounds promising. but i don’t really understand the role of the third node. and i don’t see a ‘switch parent’ mechanics.
well… there is another clue:

it should be a controller based mechanics to make one node a driver and another node driven.


OneAcc was close when he was using the ‘who is selected’ idea. it might be realized with a controller solution.


Well, i re-made this sample by using get/set value of constants in script controller instead of selected objects, it works but animation still unusable. Keys are created just by moving animation slider. May be correct solution needs smth like boolean controller somewhere.


CATHDPivotTrans controller (max 2010 and above), provides the ability to have an animated pivot point.


Edit, I didn’t saw the above reply… beat me to it :slight_smile:

Does this involve CATHDPivotTrans and animated pivot points?


Oh, I hid the link in my post as well. Highlight the underlined '. :wink:



I gave this challenge a try but didn’t succeded.
I first made a test script to get the concept.

delete $*
slidertime = 0
Pa = Point pos:[0,0,0] wirecolor:(color 200 0 0)
Pb = Point pos:[0,0,100] wirecolor:(color 200 0 0)
Offset = Pb.transform*inverse(Pa.transform)
Pb.transform = Offset*Pa.transform
Pa.transform = Pb.transform*inverse(Offset)
parentWay = 0
oldParentWay = 1

at time 10 (Pa.transform = (matrix3 [0,0,-1] [0,1,0] [1,0,0] [0,0,0])) 
at time 20 (Pb.transform = (matrix3 [0,0,-1] [-1,0,0] [0,1,0] [100,0,0])) 
for i in 0 to 20 do
at time i
	if (i == 11) then (parentWay = 1)
	if (i == 21) then (parentWay = 0)
	if (parentWay == 0) then
		Pb.transform = Offset*Pa.transform
		Offset = Pb.transform*inverse(Pa.transform)
	if (parentWay == 1) then
		Pa.transform = inverse(Offset)*Pb.transform
		Offset = Pb.transform*inverse(Pa.transform)
	--format "% %
" i Offset
	oldParentWay = parentWay

Couldn’t find a way to store transformation beetwen changing state of the system in real time.

I tried something simpler to get new ideas and here’s where I stop.
I created a controller based sytem who work but only with position.
Just feeding values from the 2 nodes with constraint list
B.parent = A
A.pos[2] get B.pos[1] in poslist[2] (move A when B moving)
B.pos[2] get -B.pos[1] in poslist[2] (counter animate)


I did several tests with Proxy Manipulator Controller and it seems I got good start with this task. It also seems stable with Biped.


  1. Create two objects (can be in same position)
  2. Assign Proxy Manipulator(PM) controller to one of them.
  3. Add another object to PM controller
  4. Switch on “Enable Rotation” and “Rotate about Manipulator”
  5. Set “Num keys” = 1

Any way is needs more test. So will be good if someone will test it too.

p.s. Personally I’m looking solution for “link” Biped with CAT rigs what to have possibility to control as by one unit.


I don’t believe the ProxyManipulator Controller will work (unless the code has been revised for later versions of Max)… I’ve tried to do this with the ProxyManipulator… IIRC, when animating the rotation of the target object it does orbit properly (because it acts like the parent)… but when animating the rotation of the object with the proxymanipulator controller… the target object’s motion is linear between the keys and it “pushes” the proxymanipulator object away from its pivot point during the rotation to maintain the fixed distance (because their distance apart is locked-- though can be edited in a sub-mode). Setting the keys to 1 to fake the interpolation is a workaround, but isn’t ideal… and you can still notice the proxymanipulator object jittering while it’s replaying the animation-- but it’s still an awesome plugin (…wish I had the coding skills to achieve it-- but I was able to at least recompile it for Max8)!

I’ve tried wiring the rotation of an object (with a TCB controller) to it’s own position track (using a second bezier controller under a position list controller) and then in the expression add the matrix I want to “orbit” around. I can get it to work for one object… but can’t get a second object to point back to the first due to illegal referencing, dependencies. I need to set up some custom attribute stuff… But I’m still working on this as time allows…


I’ll throw $100 dollars into this pot… for a solution that is backwards compatible with Max8.


I didn’t read the whole thread but I think I have solution to original problem just have a look


if you are interested in math behind have a look here

few points:
I will reference to the scene that I have in video i.e. two control locators and box which is controlled.

  1. I am not doing any kind of parent switching to break evaluation loops! You can rotate around two points simultaneously. I do some funny math to figure out what actually means to rotate around two points at the same time.
  2. Because of 1. directly moving locators is disabled. Imagine you rotate around locator1 so locator 2 get translated therefore the whole system has to move. But you just wanted rotate around locator1.
  3. Rotation of locator1 is not altered by locator2 and vice versa. You have full control of locators rotation. This way I can break the dependency loop. If you need something fixed with system just link it to the box.
  4. Position and rotation of system depends on history of locator’s rotation. So you have to specify state of the system at some time t0 and than the node do some numerical integration from time t0 to time t. In current implementation the integration is done from time t0 to time t each time you change something. So even when you change from time t to time t+dt it will recalculate everything from time t0 to (t+dt). But It could just do one more step in the integration. But the advantage of current solution is that you can randomly jump in time.
  5. It would be cool to have one move controlel which would be fix with the system but for now I don’t know how to do this. If you need some move control just edit parent start position of the multiParentNode


wow… beautiful


Ok… @lecopivo, I read your revised method you posted in your updated blog (two pivot nodes A and B, and one helper node H). I do understand your math… and I have implemented a MAXscript DLX extension that calculates the matrix exponential (using angleaxis values to first construct the required cross-product matrix…)-- thus allowing me to sum the rotations of nodes A and B (regardless of order, as you explain in your blog) and apply the total rotation to node H…

…BUT I’m struggling with how to actually implement your “update equations” in a 3ds Max construct while avoiding illegal-self referencing or circular dependencies. I’m not sure if I should try and do all of this in a custom attribute definition on the helper node H. Or try and use wire expressions or script controllers???

Any ideas or guidance from anybody would be greatly appreciated. It would save me some headaches… :banghead:


This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.