Not yet made into a routine but this section of code did work quite well.
It calculates the y rot of a vector 4096 long, its start point (current_mid) being somewhere on the surface of an imaginary sphere with a radius of 4096 and then continuing tangentially from the spheres surface to it's end point (current_t).
The y rot calulated is quit an exotic y rotation specification.... it is the y rotation relative to the XY plane. There has to be a compromise when the startpoint is towards the min or max z --- then 0 y is when the vector points to the poles (min or max y).
// (c) Jon P 2001 dx = current_mid.vx; if ( dx < 0 ) dx *= -1; dy = current_mid.vy; if ( dy < 0 ) dy *= -1; dz = current_mid.vz; if ( dz < 0 ) dz *= -1; dx2 = current_t.vx - current_mid.vx; dy2 = current_t.vy - current_mid.vy; dz2 = current_t.vz - current_mid.vz; FntPrint( "\n" ); if ( dz <= 2896 ) { if ( dx <= 2896 ) { // TOP or BOTTOM section.... // Find-out how much to adjust the Z values to effectively unrotate them // about the X axis (undoing any foreshortening)... temp = ( dz << 10 ) / dy; temp2 = temp * temp; temp2 /= 2750; temp2 += 1024; temp *= 43; temp2 += temp >> 10; FntPrint( "TOP zs=%4d ", temp2 ); // Make the adjustments to Z... dz2 = ( dz2 * temp2 ) >> 10; // Find-out how much to adjust the X values to effectively unrotate them // about the Z axis (undoing any foreshortening)... temp = ( dx << 10 ) / dy; temp2 = temp * temp; temp2 /= 2750; temp2 += 1024; temp *= 43; temp2 += temp >> 10; FntPrint( "xs=%4d ", temp2 ); // Make the adjustments to X... dx2 = ( dx2 * temp2 ) >> 10; // see if we're doing the TOP or BOTTOM section... if ( current_mid.vy < 0 ) temp = auto_arc_tan( dx2, dz2 ); // TOP section else temp = auto_arc_tan( dx2, -dz2 ); // BOTTOM section FntPrint( "ang=%d ", temp ); } else { // The LEFT or RIGHT section... // Find-out how much to adjust the Z values to effectively unrotate them // about the Y axis (undoing any foreshortening)... temp = ( dz << 10 ) / dx; temp2 = temp * temp; temp2 /= 2750; temp2 += 1024; temp *= 43; temp2 += temp >> 10; FntPrint( "RGT zs=%4d ", temp2 ); // Make the adjustments to Z... dz2 = ( dz2 * temp2 ) >> 10; // Find-out how much to adjust the Y values to effectively rotate them // about the Z axis (undoing any foreshortening)... temp = ( dy << 10 ) / dx; temp2 = temp * temp; temp2 /= 2750; temp2 += 1024; temp *= 43; temp2 += temp >> 10; FntPrint( "ys=%4d ", temp2 ); // Make the adjustments to Y... dy2 = ( dy2 * temp2 ) >> 10; // see if we're doing the RIGHT or LEFT section... if ( current_mid.vx > 0 ) temp = auto_arc_tan( dy2, dz2 ); else temp = auto_arc_tan( dy2, -dz2 ); FntPrint( "ang=%d ", temp ); } } else { // The FRONT or REAR section... // Find-out how much to adjust the Y values to effectively rotate them // about the X axis (undoing any foreshortening)... temp = ( dy << 10 ) / dz; temp2 = temp * temp; temp2 /= 2750; temp2 += 1024; temp *= 43; temp2 += temp >> 10; FntPrint( "FNT ys=%4d ", temp2 ); // Make the adjustments to Y... dy2 = ( dy2 * temp2 ) >> 10; // Find-out how much to adjust the X values to effectively unrotate them // about the Y axis (undoing any foreshortening)... temp = ( dx << 10 ) / dz; temp2 = temp * temp; temp2 /= 2750; temp2 += 1024; temp *= 43; temp2 += temp >> 10; FntPrint( "xs=%4d ", temp2 ); // Make the adjustments to X... dx2 = ( dx2 * temp2 ) >> 10; // see if we're doing the RIGHT or LEFT section... if ( current_mid.vz > 0 ) temp = auto_arc_tan( dx2, dy2 ); else temp = auto_arc_tan( dx2, -dy2 ); FntPrint( "ang=%d ", temp ); } FntPrint( "\n" );