public static TutorialAnimation loadTutorial(String filepath)
        {
            using (StreamReader reader = new StreamReader(filepath))
            {
                String line;
                String[] values;
                char[] delimeter = { ' ' };

                long timestamp;
                float x, y, z;
                long firstTimestamp = -1;

                TutorialAnimationCheckpoint tmp;
                List<TutorialAnimationCheckpoint> checkpoints = new List<TutorialAnimationCheckpoint>();

                while ((line = reader.ReadLine()) != null)
                {
                    //interpret line
                    values = line.Split(delimeter);

                    timestamp = long.Parse(values[0]);
                    x = float.Parse(values[1]);
                    y = float.Parse(values[2]);
                    z = float.Parse(values[3]);

                    if (firstTimestamp < 0)
                    {
                        firstTimestamp = timestamp;
                    }

                    tmp = new TutorialAnimationCheckpoint((timestamp - firstTimestamp), x, y, z);
                    checkpoints.Add(tmp);
                }

                TutorialAnimation animation = new TutorialAnimation(checkpoints);

                return animation;
            }
        }
        /// <summary>
        /// Computes a new point for a DVSC tutorial animation based on the
        /// current timestamp. The method assumes a linear positive advancement
        /// of time across calls.
        /// If the timestamp exceeds the time period described by the animation
        /// then a point with negative values will be returned.
        /// </summary>
        public SkeletonPoint getLocationForTimestamp(long timestamp)
        {
            wrapIndex();

            TutorialAnimationCheckpoint nextPoint = checkpoints[index];

            // If a sufficiently long period of time has passed since the last
            // point was requested the nextPoint pulled from the queue may be
            // in the past, rather than the future, respective to the provided stamp.
            // As such we will find the
            // next checkpoint in the queue past the provided timestamp.
            while (nextPoint != null &&
                    nextPoint.getTimeForPoint() < timestamp && index < (checkpoints.Count - 1))
            {
                index += 1;
                nextPoint = checkpoints[index];
            }

            if ((index >= (checkpoints.Count - 1)) && (nextPoint.getTimeForPoint() < timestamp))
            {
                wrapIndex();

                nextPoint = checkpoints[index];

                animationFinished = true;
            }

            // If there are no further checkpoints passed the provided timestamp
            // then we have reached the end of the animation; we'll signal this
            // to the user by returning a Point with negative values.
            if (nextPoint == null)
            {
                SkeletonPoint output = new SkeletonPoint();
                output.X = -1;
                output.Y = -1;
                output.Z = -1;
                return output;
            }

            // Extract Point data from previous and next checkpoints and convert them to vector data
            SkeletonPoint lastCheckpointPoint, nextCheckpointPoint;
            lastCheckpointPoint = lastCheckpointReached.getPoint();
            nextCheckpointPoint = nextPoint.getPoint();

            Vector3 lastCheckpointVector3, nextCheckpointVector3;
            lastCheckpointVector3 = new Vector3(lastCheckpointPoint.X, lastCheckpointPoint.Y, lastCheckpointPoint.Z);
            nextCheckpointVector3 = new Vector3(nextCheckpointPoint.X, nextCheckpointPoint.Y, nextCheckpointPoint.Z);
            // Compute the vector between the preceeding Point and the next defined
            // Point in the animation
            Vector3 vectorBetweenPoints = Vector3.Subtract(
                nextCheckpointVector3, lastCheckpointVector3);

            // Compute the time difference between the previously generated point
            // and the next defined point in the animation
            long timeDifference = nextPoint.getTimeForPoint()
                - lastCheckpointReached.getTimeForPoint();

            float interpolationRatio = (timestamp - lastCheckpointReached.getTimeForPoint()) / (float)timeDifference;

            // Compute a vector that will define the translation from the last
            // generated checkpoint to the Point being requested
            Vector3 mutationVector = Vector3.Multiply(
                vectorBetweenPoints, interpolationRatio);

            // Generate the Point being requested
            SkeletonPoint newPoint = new SkeletonPoint();
            newPoint.X = lastCheckpointPoint.X + mutationVector.X;
            newPoint.Y = lastCheckpointPoint.Y + mutationVector.Y;
            newPoint.Z = lastCheckpointPoint.Z + mutationVector.Z;
            // The just generated Point is now the new previous checkpoint
            // which all future requested checkpoints for this animation will
            // be computed with respect to
            lastCheckpointReached = new TutorialAnimationCheckpoint(
                timestamp, newPoint.X, newPoint.Y, newPoint.Z);

            return newPoint;
        }
 public void restartAnimation()
 {
     animationFinished = false;
     lastCheckpointReached = this.checkpoints[0];
     index = 1;
 }