Notifications
Clear all

[Closed] NodeTransformMonitor vs NodeTab

Hey guys!

So here is the deal. I have a system for my rigs that uses referencing to provide the ability of having more then one identical rig/character in the same scene. To avoid name referencing I used a combination of a NodeTab for the main reference node, and a NodeTransformMonitor in the main Node that holds the tools, to reference the Reference Node without NodeTab dependancy limitation.

Now my question to you is, which of the referencing methods is faster in the end: NodeTab or a whole bunch of NodeTransformMonitors in a MaxObjectTab?

Hope someone here will be able to provide some insights! Will be more then helpful!:thumbsup:

Cheers.
5 Replies
 PEN

Storing nodes, in a nodeTab creates a dependency that works both ways, if the node that is referenced is updated it updates the node in the nodeTab and if the node that holds the nodeTab is updated it then updates its dependents including every node in the nodeTab.

Think of nodeTransformMonitor as a container with a door that only swings one way. When a node is placed in a NTM it is protected from sending ref messages back out. So if the node that is referenced is updated it updates the node that is stored in the HTM how ever is the node that is holding the maxObjectTab and the NTMs inside it is updated it doesn’t send out a ref message to the stored nodes. This makes it faster because there is less spamming of your system. Also dependency loops are avoided because the ref messages only travel one way.

I have not used a nodeTab for what you are taking about for some time. The only time that I have is when I have wanted the nodes to get updated for real time feed back purposes.

Paul’s explanation sounds pretty spot on.

My understanding is they are basically the same thing, except with nodeTransformMonitor you can choose whether or not to constantly watch for change in the nodes being referenced. That is what the forwardTransformChangeMsgs property is for, and it makes it so nodeTransformMonitor is faster, especially when dealing with a lot of nodes.

(maxObjectTab = #(nodeTransformMonitor node:x forwardTransformChangeMsgs:true)) == (nodeTab #($))

(maxObjectTab = #(nodeTransformMonitor node:x forwardTransformChangeMsgs:false)) is quicker than (nodeTab #($))

nodeTransformMonitor with forwardTransformChangeMsgs:false is best for if you just want to store reference to the nodes for quick and easy access.

nodeTab or nodeTransformMonitor with forwardTransformChangeMsgs:true is best for if, say, you are using them in a script controller and need it so that when something on that node changes, your script controller knows to update itself.

With nodeTransformMonitor and forwardTransformChangeMsgs:false the script controller will not be notified of changes and will not update itself until the timeline is scrubbed or some other action is performed to force the update.

Alright, thanks guys! While I was wondering about this whole thing, I went to our brilliant Mathias here, who has explained several things to me (he has been dealing with SDK a bit already, so had some more info then I was aware of).

As it seems, the NodeTab is just an array, which is filled with pointers to nodes. Which basically does indeed mean that both get updated, but that is simply because they are the same thing, in cpp terms that is x->y.
NodeTransformMonitor (NTM) in turn is a whole class of it's own, which has to be created and is an actual object that watches a target node, hence even though it doesn't get directly updated, it is still a whole separate object. Update of a pointer is automatic in cpp, and requires very little, while having a new object such as NTM creates more to deal with. Here is what I read after by myself from the SDK:

[i]INodeTab - "INodeTab Class ReferenceClass representing a dynamic array of INodes."[/i]

[i]INodeTransformMonitor - "The NodeTransformMonitor class (defined in ctrl.dlc) is used to monitor a  node for its [REFMSG_CHANGE]( http://forums.cgsociety.org/group___reference___messages.html#ga6)  / PART_TM and [REFMSG_TARGET_DELETED]( http://forums.cgsociety.org/group___reference___messages.html#ga2)   messages. The NodeTransformMonitor class creates a [RefTargMonitorRefMaker]( http://forums.cgsociety.org/class_ref_targ_monitor_ref_maker.html)  instance  pointing at a node, and allows only the [REFMSG_TARGET_DELETED]( http://forums.cgsociety.org/group___reference___messages.html#ga2)  message  and the REFMSG_CHANGE message when PartID is PART_TM to propagate to the  NodeTransformMonitor's dependents. To prevent circular message loops, the  messages are not propagated if that message type is already being propagated"[/i]

So it seems to be true. An array in cpp is just a pointer, so no new objects need to exist, while a NTM is indeed a whole new object for every node we reference.
 PEN

Your right, this is indeed how it works. Speed of access might be slower as there is another node but speed of your rigs and scene are far faster using it as the ref messages are not being passed when not needed.

 PEN

Here is a speed test. nodeTab is faster but not by much and considering that you are only accessing the nodes for tools it wouldn’t make much difference at all and wouldn’t be seen by the end user.


resetMaxFile #noPrompt

boxes=for i = 1 to 1000 collect (box pos:(random [100,100,100] [-100,-100,-100]))

nodeTabPoint=point box:true size:40 pos:[-20,-120,0] wireColor:red
maxObjectTabPoint=point box:true size:40 pos:[20,-120,0] wireColor:blue
	
def=attributes test
(
	parameters testP
	(
		nodeTabArray  type:#nodeTab tabSizeVariable:true tabSize:0
		maxObjectTabArray type:#maxObjectTab tabSizeVariable:true tabSize:0
	)
)
custAttributes.add nodeTabPoint def
custAttributes.add maxObjectTabPoint def

for x in boxes do append nodeTabPoint.test.nodeTabArray x
for x in boxes do append maxObjectTabPoint.test.maxObjectTabArray (nodeTransformMonitor node:x forwardTransformChangeMsgs:false)

select nodeTabPoint
selectMore maxObjectTabPoint

clearListener()

st=timeStamp()
nodes=for x in nodeTabPoint.test.nodeTabArray collect x
ed=timeStamp()
format "nodeTabPoint Time:%
" ((ed-st)/1000.0)
--Returned: nodeTabPoint Time:0.062

st=timeStamp()
nodes=for x in maxObjectTabPoint.test.maxObjectTabArray collect x.node
ed=timeStamp()
format "maxObjectTabPoint Time:%
" ((ed-st)/1000.0)
--Returned: maxObjectTabPoint Time:0.094