Calling C++ function inside C#


#21

could you save the file in 2016 version please? maybe my old projects will be helpful…


#22

Denis, there’s no .max file inside only the source codes


#23

ouch :rofl:


#24

biped needs a specific order to set bone transforms… and it’s not a simple hierarchical order.


#25

Sadly, There is a dotnet dll that may not work on other versions, mostly because of Autodesk renaming system :slight_smile:


#26

Please let me know if you still need older version, I can re-build again :slight_smile:


#27

This is the right method to get the biped interface to call SetBipedTM:

public IIBipMaster12 GetIBipMasterInterface12(IINode node)
{
    var ptr = ((INativeObject)node.TMController.GetInterface((InterfaceID)0x9167)).NativePointer;
    return (IIBipMaster12)Autodesk.Max.Wrappers.CustomMarshalerIBipMaster12.GetInstance(string.Empty).MarshalNativeToManaged(ptr);
}

and we can check to see if the object is biped:

public static bool IsBipedNode(IINode node)
{
    IControl c = node.TMController;
    if (c == null) return false;
    if (c.ClassID.PartA == 0x9154) return true;
    if (c.ClassID.PartA == 0x9156) return true;
    if (c.ClassID.PartA == 0x3011) return true;
    return false;
}

Then we can set transform like this:

private void Part_Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (canChange == true)
    {
        int time = coreInterface.Time;
        float val = Convert.ToSingle(e.NewValue / 100d);
        globalInterface.DisableRefMsgs();
        for (int i = 0; i < sourceNodes.Count; i++)
        {
            IMatrix3 blendTM = BlendMatrix(sourceTMs[i], targetTMs[i], val);
            if (IsBipedNode(sourceNodes[i]))
            {
                IIBipMaster12 iBipMaster12 = GetIBipMasterInterface12(sourceNodes[i]);
                int id = 0;
                int link = 0;
                iBipMaster12.GetIdLink(sourceNodes[i], ref id, ref link);
                iBipMaster12.StartSettingBipedKeys();
                iBipMaster12.SetBipedTM(time, blendTM, id, link);
                iBipMaster12.StopSettingBipedKeys();
            }
            else
            {
                sourceNodes[i].SetNodeTM(time, BlendMatrix(sourceTMs[i], targetTMs[i], val));
            }
        }
        globalInterface.EnableRefMsgs();
        for (int i = 0; i < sourceNodes.Count; i++)
        {
            sourceNodes[i].InvalidateTM();
        }
        coreInterface.RedrawViews(time, RedrawFlags.Normal, null);
    }
}

#28

Now the code works in this case as well.


#29

Because we start from the root node in the scene, it works on the hierarchy. (if we use the SetBipedTM for biped parts).


#30

This is the update so far: TestProject(2020).rar (6.2 MB)


#31

This is another example that tool doesn’t work: TestMaxFile(2016).max (1.0 MB)


#32

oops, it was my mistake, StartSettingBipedKeys and StopSettingBipedKeys should be outside the loop. Now it’s work on the latest scene as well. :slight_smile:


#33

I ended up to save and load transforms locally. First I tried to set the transform controller, but I waste my time:

So the best method is to make all transforms locally:

private IMatrix3 GetNodeLocalTM(IINode node)
{
    int time = coreInterface.Time;
    IMatrix3 nodeTM = node.GetNodeTM(time, null);
    if (IsBipedNode(node))
    {
        IIBipMaster9 iBipMaster9 = GetIBipMasterInterface9(node);
        IINode footstepNode = iBipMaster9.GetNode(15, 0);
        nodeTM.MultiplyBy(globalInterface.Inverse(footstepNode.GetNodeTM(time,null)));
    }
    else
    {
        nodeTM.MultiplyBy(globalInterface.Inverse(node.GetParentTM(time)));
    }
    return nodeTM;
}

private void SetNodeLocalTM(IINode node, IMatrix3 matrix)
{
    int time = coreInterface.Time;
    if (IsBipedNode(node))
    {
        IIBipMaster9 iBipMaster9 = GetIBipMasterInterface9(node);
        int id = 0;
        int link = 0;
        iBipMaster9.GetIdLink(node, ref id, ref link);
        IINode footstepNode = iBipMaster9.GetNode(15, 0);
        matrix.MultiplyBy(footstepNode.GetNodeTM(time,null));
        iBipMaster9.SetBipedTM(time, matrix, id, link);
    }
    else
    {            
        matrix.MultiplyBy(node.GetParentTM(time));
        node.SetNodeTM(time, matrix);
    }
}