Community
3ds Max Programming
Welcome to Autodesk’s 3ds Max Forums. Share your knowledge, ask questions, and explore popular 3ds Max SDK, Maxscript and Python topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Never ending node transform detection through ControllerOtherEvent (C++ SDK)

15 REPLIES 15
Reply
Message 1 of 16
Anonymous
1422 Views, 15 Replies

Never ending node transform detection through ControllerOtherEvent (C++ SDK)

I'm using the  ControllerOtherEvent to detect changes related to node's transformation matrices. The steps I follow are:

  1. Get the matrix of the transformed node (INode::GetNodeTM)
  2. Perform some operations on that matrix to clamp it to a surface
  3. Use that resultant matrix to set the final matrix of the given node (INode::SetNodeTM)

The problem is that, applying changes to the node's matrix in step (3) will derive on the ControllerOtherEvent being called again and again, since the node's controller is modified of course. In the viewport, you'll see my node moving until it reaches the max/min of allowed coordinates.

 

Is there an elegant way to solve this? How can I manage to set the new node matrix without this event being called forever?

 

Thanks!

15 REPLIES 15
Message 2 of 16
istan
in reply to: Anonymous

What do you actually want to do? Can't you make it more simple by using the RedrawCallback instead?

Message 3 of 16
Anonymous
in reply to: istan

Hi @istan , thanks for replyign.

 

What I'm trying to do is to grab the matrix of a node that was just transformed, and the apply to it some  additional operations that will clamp the node to a surface. Since those operations will modify the point position, I need to find a way to redraw the node with that resultant matrix (the clamped one).

 

The reason I'm using ControllerOtherEvent is because it will detect the node's transform, so I thought it was a good place to perform the operation. However, I don't know how I should assign that new matrix to the node so the node is clamped to the surface after the calculations.

 

void MyNodeEventCallback::ControllerOtherEvent(NodeKeyTab &nodes)
{
    INode *node;
    int nodeCount = nodes.Count();
    Matrix3 inMat, outMat;

    if (nodeCount<1)
        return;

    for (int i=0; i<nodecount; ++i)="" {="" node="NodeEventNamespace::GetNodeByKey(nodes[i])" inmat="node-">GetNodeTM(time);
if (IsPointHelperType(node)) {
MyPointHelper *ptH = (MyPointHelper*) node->GetObjectRef();
           
// apply some additional operations to the matrix of transformed node
outMat = ptH->ClampToSurface(inMat);

// here is the problem, applying the the resultant matrix (outMat) to the node
// derives in this ControllerEvent being raised again and again
  inMat = node->SetNodeTM(time); } }
GetCOREInterface()->ForceCompleteRedraw(); }</nodecount;></nodecount;>

 

Thanks in advance 🙂

Message 4 of 16
denisT.MaxDoctor
in reply to: Anonymous

You set 'clamped' transformation matrix inside event callback which causes this event firing again and again... 

You have two choices:

1. Disable this callback at the moment of your 'transform' modification, and enable it back after the modification.

2. Flag the currently processing node with a special custom flag (using the Animatable flags - Set/Clear/Test AFlagEx), and process nodes based on their current status (means do process or skip). 

 

I would do both.

Message 5 of 16

actually... I would write my own position controller which will do this 'clamping', and apply it to a specified nodes. It will not need any catching of transform events (which are anyway to late in case what you do).  

Message 6 of 16
istan
in reply to: denisT.MaxDoctor

I'm just curious: How would you catch an interactive TM change (i.e. user moves a node per mouse) in such a controller ?

Message 7 of 16
Anonymous
in reply to: denisT.MaxDoctor


1. Disable this callback at the moment of your 'transform' modification, and enable it back after the modification.


I tried that first solution you gave me with the following:

DetectRaisedPointHelperNodeEvents(FALSE);
node->SetNodeTM(time, outMat);
DetectRaisedPointHelperNodeEvents(TRUE);

Where DetectRaisedPointHelperNodeEvents, will register and unregister the INodeEventCallback. And it works sometimes but the transform is a lot flickery. I debugged it and the node transform seems to change every time, even when I'm not moving it.

Message 8 of 16
denisT.MaxDoctor
in reply to: istan


@istan wrote:

I'm just curious: How would you catch an interactive TM change (i.e. user moves a node per mouse) in such a controller ?


it depends on what kind of control i will do. i would probably do a Limit control extension. so i will not care about interactive 'change'. the main position control will do it. 

 

your question also explains why the 'transform change event' solution can't work correct. we will always see 'flicker' because the event fires after transform changed and transform controls are validated (and most likely the scene redrawn). that's why i am not sure this solution will work with built-in rendering.

 

  

 

Message 9 of 16

another solution might be a special 'constraint' control (which also doesn't need 'interactive change' implementation). this 'constrain' control might be added as sub-control to a Position List.

 

if we want to change the whole node transform (not only its position), the task becomes more complicated. but the translation is the last transformation operation, and we still can do 'orientation' constraint on position control level (like a attach control does do it, for example). 

it's easy to experiment with this idea playing with MXS scripted controls before going to API implementation.  

Message 10 of 16
istan
in reply to: denisT.MaxDoctor

Hehe... Therefore I wrote: Think about using a RedrawCallback. IMHO this is the most stable and most RT responsive version since Max 9. It handles of course the whole TM and not only the translation.

Message 11 of 16
denisT.MaxDoctor
in reply to: istan

RedrawCallback can't be used during rendering. And it's also too late  

Message 12 of 16
istan
in reply to: denisT.MaxDoctor

Is for sure, but I was talking about interactive mouse actions.

Message 13 of 16
denisT.MaxDoctor
in reply to: istan


@istan wrote:

Is for sure, but I was talking about interactive mouse actions.


as I could understand there is a problem with 'flickering'. Redraw callback can't solve this problem. It sent after everything was already happened - transform changed and view drawn.

 

Message 14 of 16
istan
in reply to: denisT.MaxDoctor

Let us end this discussion here.

My stuff is working, I just thought you probably found a better approach.

Many Thanks.

Message 15 of 16
Anonymous
in reply to: istan

Thanks guys for contributing to solving my problem. Enabling/disabling the node event handling when setting the new position works. The 'flickery' stuff is because the node is redrawn before AND after setting the new position.  Anyway, I'll leave it that way and in the mean time I'll explore your other options.

 

@istanif it's possible, could you pls elaborate more? I'm curious about your idea but I couldn't follow it 😞

 

Thanks again!

Message 16 of 16
denisT.MaxDoctor
in reply to: istan


@istan wrote:

My stuff is working, I just thought you probably found a better approach.

 


the better and right approach (IMHO) to write your own controller. It's easy now to experiment, because mxs scripted controllers are available in the recent versions.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report