/// <summary>
 /// Setup constructor
 /// </summary>
 /// <param name="camera">Camera, used to determine patch error</param>
 /// <param name="generator">Object used to generate the patch vertices</param>
 /// <param name="patch">Terrain patch</param>
 /// <param name="calculatePatchError">If true, the maximum error between the patch geometry and the terrain model is calculated</param>
 private unsafe TerrainPatchBuildItem( IProjectionCamera camera, ITerrainPatchGenerator generator, ITerrainPatch patch, bool calculatePatchError )
 {
     m_Camera = camera;
     m_Generator = generator;
     m_Patch = patch;
     m_CalculatePatchError = calculatePatchError;
 }
        /// <summary>
        /// Patches are defined in a local space. This determines the planet-space parameters of a patch
        /// </summary>
        public void SetPatchPlanetParameters( ITerrainPatch patch )
        {
            float radius = SpherePlanet.PlanetModel.Radius.ToRenderUnits;

            Point3 edge = patch.LocalOrigin + ( patch.LocalUAxis / 2 );
            Point3 centre = edge + ( patch.LocalVAxis / 2 );

            Point3 plEdge = ( edge.ToVector3( ).MakeNormal( ) * radius ).ToPoint3( );
            Point3 plCentre = ( centre.ToVector3( ).MakeNormal( ) * radius ).ToPoint3( );

            patch.SetPlanetParameters( plCentre, plCentre.DistanceTo( plEdge ) );
        }
 /// <summary>
 /// Generates vertices for a patch. Calculates maximum error between this patch and next higher detail patch
 /// </summary>
 /// <param name="patch">Patch</param>
 /// <param name="res">Patch resolution</param>
 /// <param name="firstVertex">Patch vertices</param>
 /// <param name="error">Maximum error value between this patch and higher level patch</param>
 public unsafe void GenerateTerrainPatchVertices( ITerrainPatch patch, int res, TerrainVertex* firstVertex, out float error )
 {
     SetPatchPlanetParameters( patch );
     SafeTerrainGenerator.GenerateVertices( patch.LocalOrigin, patch.LocalUStep, patch.LocalVStep, res, res, patch.Uv, patch.UvResolution, firstVertex, out error );
 }
        /// <summary>
        /// Allocates a terrain patch build item from an internal pool
        /// </summary>
        public static TerrainPatchBuildItem Allocate( IProjectionCamera camera, ITerrainPatchGenerator generator, ITerrainPatch patch, bool calculatePatchError )
        {
            if ( s_BuildItems.Count == 0 )
            {
                return new TerrainPatchBuildItem( camera, generator, patch, calculatePatchError );
            }
            TerrainPatchBuildItem item = s_BuildItems[ 0 ];
            s_BuildItems.RemoveAt( 0 );

            item.m_Camera = camera;
            item.m_Generator = generator;
            item.m_Patch = patch;
            item.m_CalculatePatchError = calculatePatchError;

            return item;
        }