1. This forum is obsolete and read-only. Feel free to contact us at support.keenswh.com

How do I get the world position and rotation of a ship?

Discussion in 'Programming (In-game)' started by picklerok, Jul 1, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. picklerok

    picklerok Junior Engineer

    Messages:
    544
    Is there a way to get the position and rotation of the ship that the programmable block is on, as well as the position and rotation of a ship detected by sensors? I'm pretty sure that it is at least possible to do the latter, but I don't remember how.
     
  2. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    You can get any IMyTerminalBlock's position with Vector3D block.GetPosition().
    If you do that with several blocks, you can define vectors and thus determine the orientation like Up, Down, Left, Right, Forward, Backward and thus full orientation.
     
  3. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    You don't need blocks anymore, use IMyCubeGrid.GridIntegerToWorld instead.

    Cast the sensor's LastDetectedEntity to IMyCubeGrid and use the above.
     
  4. picklerok

    picklerok Junior Engineer

    Messages:
    544
    That works, but how do I get the rotation?
     
  5. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    For the "rotation" or "orientation" of a ship you get an anchor point like the block at (0,0,0). This is the center.

    Then you assign a forward position where one of the X-/Y-/Z-values is -1 or 1 depending on what your desired forward direction is. This actually changes from ship to ship. There is a default orietation, but you are not bound to it as your cockpit (which determines your desired local orientaion) can have any orientation within the grid.

    The next you need to define is your left/right and up/down direction. Each again with just one value of the Vector3 as -1 or 1 and any other position 0. Though all vectors have to be linear independend from each other.

    Also note, which is obvious but still important to point out at least once:
    Forward = -Backward
    Left = -Right
    Up = -Down

    Example setups:
    Forward: (0, -1, 0) > Backward (0, 1, 0)
    Left: (0, 0, -1) > Right (0, 0, 1)
    Up: (1, 0, 0) > Down (-1, 0, 0)

    If you got those, you then can gather the world coordinates for the required points and get the world vectors which are your actual orientation in the world.
     
  6. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    Well, that depends on what you mean by "rotation". As player2k indicated, there are a couple different orientations we could be talking about. Like he said, most often when people ask about this, they want the cockpit orientation.

    You should be able to get whatever you want from this, though:
    Code:
    MatrixD GetGrid2WorldTransform(IMyCubeGrid grid)
    {
        Vector3D origin=grid.GridIntegerToWorld(new Vector3I(0,0,0));
        Vector3D plusY=grid.GridIntegerToWorld(new Vector3I(0,1,0))-origin;
        Vector3D plusZ=grid.GridIntegerToWorld(new Vector3I(0,0,1))-origin;
        return MatrixD.CreateScale(grid.GridSize)*MatrixD.CreateWorld(origin,-plusZ,plusY);
    }
    
    MatrixD GetBlock2WorldTransform(IMyCubeBlock blk)
    {
        Matrix blk2grid;
        blk.Orientation.GetMatrix(out blk2grid);
        return blk2grid*
               MatrixD.CreateTranslation(((Vector3D)new Vector3D(blk.Min+blk.Max))/2.0)*
               GetGrid2WorldTransform(blk.CubeGrid);
    }
    
    //Example
    void Main(string argument)
    {
        var l=new List<IMyTerminalBlock>();
        GridTerminalSystem.GetBlocksOfType<IMyTextPanel>(l);
        var lcd=l[0] as IMyTextPanel;
    
        lcd.WritePublicText("");
        GridTerminalSystem.GetBlocks(l);
        for(int i=0;i<l.Count;++i)
        {
            //Calculate error between our world matrix and the game's GetPosition()
            MatrixD g2w=GetGrid2WorldTransform(l[i].CubeGrid);
            Vector3D gridPos=(new Vector3D(l[i].Min+l[i].Max))/2.0; //( .Position is a problem for even size blocks)
            Vector3D calcPos=Vector3D.Transform(gridPos,ref g2w);
            double err=(l[i].GetPosition()-calcPos).Length();
     
            //Find the world "forward" vector for the block
            MatrixD b2w=GetBlock2WorldTransform(l[i]);
            Vector3D fwd=b2w.Forward;
            fwd.Normalize(); //(Need to normalize because the above matrices are scaled by grid size)
    
            lcd.WritePublicText(String.Format("{0}: Error={1}\n    fwd={2}\n",l[i].CustomName,err,fwd),true);
        }
    } 
    I wrote this just now so it hasn't been tested extensively, but the little testing I did do indicates no problems.

    Also, be careful of Matrix D.Up. I haven't checked it recently, but months ago it gave garbage results. Test it before you rely on it. Forward and Left are fine.
     
    Last edited: Jul 21, 2015
Thread Status:
This last post in this thread was made more than 31 days old.