public void addKeyFrameRotationAngles(int keyFrameIndex, float x, float y, float z) {
        Rotation r = getRotationForFrame(keyFrameIndex);
        r.set(x, y, z);

        // if the delta of Euler angles is higher than PI, we create intermediate keyframes
        // since we are using quaternions and slerp for rotation interpolation, we cannot interpolate over an angle higher than PI
        int prev = getPreviousKeyFrame(keyFrameIndex, keyFramesRotation);
        if (prev != -1) {
            //previous rotation keyframe
            Rotation prevRot = keyFramesRotation[prev];
            //the maximum delta angle (x,y or z)
            float delta = Math.max(Math.abs(x - prevRot.eulerAngles.x), Math.abs(y - prevRot.eulerAngles.y));
            delta = Math.max(delta, Math.abs(z - prevRot.eulerAngles.z));
            //if delta > PI we have to create intermediates key frames
            if (delta >= FastMath.PI) {
                //frames delta
                int dF = keyFrameIndex - prev;
                //angle per frame for x,y ,z
                float dXAngle = (x - prevRot.eulerAngles.x) / dF;
                float dYAngle = (y - prevRot.eulerAngles.y) / dF;
                float dZAngle = (z - prevRot.eulerAngles.z) / dF;

                // the keyFrame step
                int keyStep = (int) (dF / delta * EULER_STEP);
                // the current keyFrame
                int cursor = prev + keyStep;
                while (cursor < keyFrameIndex) {
                    //for each step we create a new rotation by interpolating the angles
                    Rotation dr = getRotationForFrame(cursor);
                    dr.masterKeyFrame = keyFrameIndex;
                    dr.set(prevRot.eulerAngles.x + cursor * dXAngle, prevRot.eulerAngles.y + cursor * dYAngle, prevRot.eulerAngles.z + cursor * dZAngle);
                    cursor += keyStep;
                }

            }
        }

    }
Adds a key frame for the given rotation at the given key frame index.<br>
Rotation is expressed by Euler angles in radians.<br>
Note that the generated rotation will be stored as a quaternion and interpolated using a spherical linear interpolation (slerp)<br>
Hence, this method may create intermediate keyFrames if the interpolation angle is higher than PI to ensure continuity in animation<br>

@param keyFrameIndex the index at which the keyFrame must be inserted
@param x the rotation around the x axis (aka yaw) in radians
@param y the rotation around the y axis (aka roll) in radians
@param z the rotation around the z axis (aka pitch) in radians
jme3-core/src/main/java/com/jme3/animation/AnimationFactory.java