Sometimes you need to perform cumbersome math just to to put an object into the right 3D place or, as for my specific case, to get the right relative position of two objects (from two different aircrafts). Suppose you need to know the coordinates of a point of a given aircraft (e.g.because you are actually going to draw an object in that precise point) What you have is the aircraft position (it's geometric center in x-plane local coordinates + heading, roll and pitch) and the offset of your point in aircraft coordinates. what you need is the point position (x,y,z in x-plane local coordinates) Transform3D (code below) will take as input: inLocalCoords: the offest of your object in acf coordinates inMap: the coordinates and angles of the aircraft and will pop out: outCoords: the coordinates of your object in x.plane "local" coordinates (Bottom line: Unless it's already there, this should really go into Gizmo) void Transform3D(const double inLocalCoords[3], /*acf coordinates*/ const double inMap[6], /*x, y, z, heading, pitch, roll (X-Plane has angles in degrees)*/ double outCoords[3]){ //http://en.wikipedia.org/wiki/Rotation_matrix //http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html //Make constants easier to handle. //Put angles into radians. const double H_rad = -inMap[3]*DEG2RAD; //heading const double P_rad = inMap[4]*DEG2RAD; //pitch const double R_rad = -inMap[5]*DEG2RAD; //roll const double cos_H = cos(H_rad); const double sin_H = sin(H_rad); const double cos_P = cos(P_rad); const double sin_P = sin(P_rad); const double cos_R = cos(R_rad); const double sin_R = sin(R_rad); //Pitch rotation matrix const double Mx[3][3] = { { 1, 0, 0 }, { 0, cos_P, -sin_P }, { 0, sin_P, cos_P } }; //Heading rotation matrix const double My[3][3] = { { cos_H, 0, sin_H }, { 0, 1, 0 }, { -sin_H, 0, cos_H } }; //Roll rotation matrix const double Mz[3][3] = { { cos_R, -sin_R, 0 }, { sin_R, cos_R, 0 }, { 0, 0, 1 } }; //What we want is out = [Mx*My*Mz] * in //We will use three consequent multiplications //The _only_ correcy sequence is //Mz //Mx //My //otherwise you get garbage (see multiplication rules for matrices...) double step1[3]; double step2[3]; // step1 = Mz * in mmult(inLocalCoords, Mz, step1); // step2 = Mx * step1 mmult(step1, Mx, step2); // out = My * step2 mmult(step2, My, outCoords); /*Finally, apply translation*/ for(int i=0; i<3; i++) outCoords[i]+=inMap[i]; /* X, Y, Z*/ } void mmult(const double inX[3], const double R[3][3], double outX[3]){ for(int n=0; n<3; n++) outX[n]=0; for(int i=0; i<3; i++) for(int j=0; j<3; j++) outX[i] += R[i][j] * inX[j]; } edited: using the code tag a few missing indices just popped out again