could you save the file in 2016 version please? maybe my old projects will be helpful…
Calling C++ function inside C#
biped needs a specific order to set bone transforms… and it’s not a simple hierarchical order.
Sadly, There is a dotnet dll that may not work on other versions, mostly because of Autodesk renaming system
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);
}
}
Because we start from the root node in the scene, it works on the hierarchy. (if we use the SetBipedTM for biped parts).
oops, it was my mistake, StartSettingBipedKeys and StopSettingBipedKeys should be outside the loop. Now it’s work on the latest scene as well.
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);
}
}