public float[] toAngles(float[] angles) {
        if (angles == null) {
            angles = new float[3];
        } else if (angles.length != 3) {
            throw new IllegalArgumentException("Angles array must have three elements");
        }

        float sqw = w * w;
        float sqx = x * x;
        float sqy = y * y;
        float sqz = z * z;
        float unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise
        // is correction factor
        float test = x * y + z * w;
        if (test > 0.499 * unit) { // singularity at north pole
            angles[1] = 2 * FastMath.atan2(x, w);
            angles[2] = FastMath.HALF_PI;
            angles[0] = 0;
        } else if (test < -0.499 * unit) { // singularity at south pole
            angles[1] = -2 * FastMath.atan2(x, w);
            angles[2] = -FastMath.HALF_PI;
            angles[0] = 0;
        } else {
            angles[1] = FastMath.atan2(2 * y * w - 2 * x * z, sqx - sqy - sqz + sqw); // yaw or heading
            angles[2] = FastMath.asin(2 * test / unit); // roll or bank
            angles[0] = FastMath.atan2(2 * x * w - 2 * y * z, -sqx + sqy - sqz + sqw); // pitch or attitude
        }
        return angles;
    }
Converts to equivalent Tait-Bryan angles, to be applied in x-z-y
intrinsic order or y-z'-x" extrinsic order, for instance by
{@link #fromAngles(float[])}. The current instance is unaffected.

@see
<a href=
"http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm">
http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm
</a>

@param angles storage for the result, or null for a new float[3]
@return an array of 3 angles (in radians, either <code>angles</code> or a
    new float[3], the X angle in angles[0], the Y angle in angles[1], and
    the Z angle in angles[2])
@throws IllegalArgumentException if {@code angles.length != 3}
jme3-core/src/main/java/com/jme3/math/Quaternion.java