DotNet/SDK IntersectRay co-ordinate space issues


#1

Greetings, still struggling with an SDK port of a heavy lifting IntersectRay loop, and running into some trouble with the difference between the coordinate space maxScript IntersectRayEx works in, and the C# or C++ equivalents…

After some googling, I realised I needed the ray in my hit test to be in object space, but Can’t seem to get it back out again… I’m not quite sure where I’m going wrong?

Code sample here:

Thanks for the help!

Mikie

Edit: Adding the solution I found…

This didn’t work:



      // cast as tri-object, as we know it will work by this point
      var triOriginal = objOriginal as ITriObject;


      // get various cooridnate spaces
      var TTM = Target.GetNodeTM(Ip.Time, intv);
      var InvTTM = Target.GetNodeTM(Ip.Time, intv);
      var STM = Source.GetNodeTM(Ip.Time, intv);
      var InvSTM = Source.GetNodeTM(Ip.Time, intv);
      InvTTM.Invert();
      InvSTM.Invert();

      // ray in world space (Source is always in world space, rayDir = (0,0,-1, or 0,0,1))
      Rhey = Global.Ray.Create(STM.Trans, RayDir);

      // put ray in target object space
      Rhey.P = InvTTM.Multiply(STM).Trans;
      Rhey.Dir = Global.VectorTransform(Rhey.Dir, InvTTM);
      Global.Normalize(Rhey.Dir);

      var res = triOriginal.Mesh.IntersectRay(Rhey, ref dist, nor, ref fi, bary);

      HitPos.X = Rhey.P.X + Rhey.Dir.X * dist; // broken out for quicker debug in attached process
      HitPos.Y = Rhey.P.Y + Rhey.Dir.Y * dist;
      HitPos.Z = Rhey.P.Z + Rhey.Dir.Z * dist;

      // Back into world space?
      HitPos = Global.VectorTransform(HitPos, TTM);

      Autodesk.Max.GlobalInterface.Instance.TheListener.EditStream.Printf($"Source: {Source.Name} | ");
      Autodesk.Max.GlobalInterface.Instance.TheListener.EditStream.Printf($"HitPos X: {HitPos.X} Y: {HitPos.Y} Z: {HitPos.Z}
");


This did work… Good old trial and error to the rescue. I kind of (but not completely) understand where I went wrong, and hopefully others can learn as well…


      // cast as tri-object, as we know it will work by this point
      var triOriginal = objOriginal as ITriObject;


      // get various cooridnate spaces
      var TTM = Target.GetObjectTM(Ip.Time, intv);
      var InvTTM = Target.GetObjectTM(Ip.Time, intv);
      var STM = Source.GetNodeTM(Ip.Time, intv);
      var InvSTM = Source.GetNodeTM(Ip.Time, intv);
      InvTTM.Invert();
      InvSTM.Invert();

      // ray in world space (Source is always in world space, rayDir = (0,0,-1, or 0,0,1))
      Rhey = Global.Ray.Create(STM.Trans, RayDir);

      // put ray in target object space
      Rhey.P = STM.Multiply(InvTTM).Trans;
      Rhey.Dir = Global.VectorTransform(Rhey.Dir, InvTTM);
      Global.Normalize(Rhey.Dir);

      var res = triOriginal.Mesh.IntersectRay(Rhey, ref dist, nor, ref fi, bary);

      // Hit position in Object space
      HitPos = Rhey.P.Add(Rhey.Dir.MultiplyBy(dist));

      // Back into World Space
      var resMat = Global.Matrix3.Create(true);
      resMat.Trans = HitPos;
      resMat = resMat.Multiply(TTM);
      HitPos = resMat.Trans;

      // Debug to 3ds Max Listener
      Autodesk.Max.GlobalInterface.Instance.TheListener.EditStream.Printf($"Source: {Source.Name} | ");
      Autodesk.Max.GlobalInterface.Instance.TheListener.EditStream.Printf($"HitPos X: {HitPos.X} Y: {HitPos.Y} Z: {HitPos.Z}
");


Converting simple renderer script to max sdk plugin