List <Task <IQuadNode> > CreateBackgroundSplitTasks(DoubleVector3 cameraLocation, DoubleVector3 planetLocation)
        {
            // TODO: there's a problem with this algorithm.  If we need to split very deeply because for example
            // the camera is teleported to the surface, we only split one level at a time and wait for that level
            // to finish and for the next update sweep to occur before queuing splits for the next level.  There
            // may be wasted time in there (not clear yet).  We also spend time generating meshes for quads that
            // we know we don't need.  Ideally we'd jump straight to rendering meshes for the new leaves and worry
            // about rendering meshes for the intermediate nodes later when we need them.  This means we need a
            // general way to delay completing a merge (continuing to render its children in the meantime) until
            // a mesh is rendered for that node.  Once we have that behavior
            // we can maybe throw away the vertex buffers for all non-leaf meshes to save memory and regenerate them
            // as needed.  That would take more CPU overall but it's not time sensitive because we'd just keep
            // rendering the child nodes until we got around to it.  That would be a problem only if we end up
            // overloading the GPU but in many cases that wouldn't happen because the merging nodes would be behind
            // the camera as it travels and thus not rendered.
            // Potential problem: we don't know for sure if a node needs to be split until after we generate its mesh.

            _splitInProgress = true;
            var subextents = _extents.Split();

            return(subextents.Select(extent => Task <IQuadNode> .Factory.StartNew(() =>
            {
                var node = _quadNodeFactory.Create();
                node.Initialize(_planetRadius, _planeNormalVector, _uVector, _vVector, extent, Level + 1);
                node.Update(cameraLocation, planetLocation);
                return node;
            }, _cancellationTokenSource.Token, TaskCreationOptions.None, _taskSchedulerFactory.CreateForLevel(Level))).ToList());
        }
        private IQuadNode CreateFace(double planetRadius, Vector3 normalVector)
        {
            var face = _quadNodeFactory.Create();

            var orientationVectors = _faceOrientations[normalVector];
            var u = orientationVectors[0];
            var v = orientationVectors[1];

            face.Initialize(planetRadius, normalVector, u, v, new QuadNodeExtents(-1.0, 1.0, -1.0, 1.0), 0);

            return(face);
        }