/// <summary>
 /// Generates an animation sequence of wave heightmaps or normalmaps
 /// </summary>
 public WaveAnimation GenerateSequence( WaveAnimationParameters parameters, IProgressMonitor progress )
 {
     Arguments.CheckNotNull( parameters, "parameters" );
     if ( parameters.StoreHeights )
     {
         return GenerateHeightmapSequence( parameters, progress );
     }
     return GenerateNormalMapSequence( parameters, progress );
 }
        /// <summary>
        /// Setup constructor
        /// </summary>
        /// <param name="uiProvider">UI provider. If null, no error messages are shown to the user</param>
        /// <param name="view">View to control</param>
        /// <param name="model">Animation model</param>
        /// <param name="workQueue">Work queue</param>
        public WaveAnimatorController( IMessageUiProvider uiProvider, IWaveAnimatorView view, WaveAnimationParameters model, IWorkItemQueue workQueue )
        {
            Arguments.CheckNotNull( view, "view" );
            Arguments.CheckNotNull( model, "model" );
            Arguments.CheckNotNull( workQueue, "workQueue" );

            view.Model = model;
            view.GenerateAnimation += OnGenerateAnimation;

            m_View = view;
            m_WorkQueue = workQueue;
            m_Marshaller = new DelegateMarshaller( );
            m_UiProvider = uiProvider;
        }
 /// <summary>
 /// Generates an animation sequence of wave normal maps
 /// </summary>
 public WaveAnimation GenerateNormalMapSequence( WaveAnimationParameters parameters, IProgressMonitor progress )
 {
     Arguments.CheckNotNull( parameters, "parameters" );
     progress = progress ?? ProgressMonitor.Null;
     float progressPerFrame = 1.0f / parameters.Frames;
     m_Map = null;
     m_InvMap = null;
     Bitmap[] results = new Bitmap[ parameters.Frames ];
     for ( int i = 0; i < parameters.Frames; ++i )
     {
         results[ i ] = GenerateNormalMap( parameters, parameters.Time * ( ( float )i / ( parameters.Frames - 1 ) ), parameters.Time, progress, i * progressPerFrame, progressPerFrame );
     }
     return new WaveAnimation( results );
 }
 /// <summary>
 /// Setup constructor
 /// </summary>
 /// <param name="uiProvider">UI provider. If null, no error messages are shown to the user</param>
 /// <param name="view">View to control</param>
 /// <param name="model">Animation model</param>
 public WaveAnimatorController( IMessageUiProvider uiProvider, IWaveAnimatorView view, WaveAnimationParameters model )
     : this(uiProvider, view, model, ExtendedThreadPool.Instance)
 {
 }
 /// <summary>
 /// Animation generator function
 /// </summary>
 private void GenerateAnimationWorker( IProgressMonitor monitor, WaveAnimationParameters model )
 {
     WaveAnimationGenerator generator = new WaveAnimationGenerator( );
     WaveAnimation animation = generator.GenerateHeightmapSequence( model, monitor );
     m_Marshaller.PostAction( m_View.ShowAnimation, animation );
 }
 private ComplexF[] GetInvFrequencyMap( WaveAnimationParameters parameters )
 {
     if ( m_InvMap == null )
     {
         ComplexF[] frequencyMap = new ComplexF[ parameters.Width * parameters.Height ];
         GenerateInitialFrequencyMap( parameters, frequencyMap, -1 );
         m_InvMap = frequencyMap;
     }
     return m_InvMap;
 }
        private Bitmap GenerateNormalMap( WaveAnimationParameters parameters, float t, float maxT, IProgressMonitor progress, float curProgress, float progressPerFrame )
        {
            int width = parameters.Width;
            int height = parameters.Height;
            ComplexF[] frequencyMap = GetFrequencyMap( parameters );
            ComplexF[] invFrequencyMap = GetInvFrequencyMap( parameters );

            Bitmap bmp = new Bitmap( width, height, PixelFormat.Format24bppRgb );
            ComplexF[] resMap = Generate( frequencyMap, invFrequencyMap, width, height, t, maxT, true );

            Fourier.FFT2( resMap, width, height, FourierDirection.Backward );
            for ( int y = 0; y < height; ++y)
            {
                for ( int x = 0; x < width; ++x )
                {
                    byte nX = ( byte )( Math.Max( 0, Math.Min( 256, 128 + resMap[ x + y * width ].Re * 8 ) ) );
                    byte nY = ( byte )( Math.Max( 0, Math.Min( 256, 128 + resMap[ x + y * width ].Im * 8 ) ) );
                    bmp.SetPixel( x, y, Color.FromArgb( nX, 0, nY ) );
                }
                progress.UpdateProgress( curProgress + progressPerFrame * ( y / ( float )( height - 1 ) ) );
            }

            return bmp;
        }
        private static float GetWaveSpectrum( WaveAnimationParameters parameters, Vector2 windDir, Vector2 k )
        {
            float lenK = k.Length;
            if ( lenK < 0.000001f )
            {
                return 0;
            }

            Vector2 nK = k / lenK;
            float a = parameters.WaveModifier;
            float l = parameters.WindSpeed * parameters.WindSpeed / 10;
            float lenK2 = lenK * lenK;
            float f = ( float )Math.Exp( -1 / ( lenK2 * l * l ) ) / ( lenK2 * lenK2 );
            float wDotK = windDir.Dot( nK );

            return f * wDotK * wDotK * a;
        }
        private static void GenerateInitialFrequencyMap( WaveAnimationParameters parameters, ComplexF[] frequencyMap, float kMul )
        {
            int width = parameters.Width;
            int height = parameters.Height;
            float angle = parameters.WindDirectionDegrees * Constants.DegreesToRadians;
            Vector2 windDir = new Vector2( Functions.Sin( angle ), Functions.Cos( angle ) );
            Random rnd = new Random( );
            for ( int y = 0; y < height; ++y )
            {
                float ky = GetKComponent( y, height ); //Pi * y / height;
                for ( int x = 0; x < width; ++x )
                {
                    float kx = GetKComponent( x, width ); //Pi * ( x / width );

                    float Er = ( 2.0f * ( float )rnd.NextDouble( ) ) - 1.0f;
                    float Ei = ( 2.0f * ( float )rnd.NextDouble( ) ) - 1.0f;

                    float P = ( float )Math.Sqrt( GetWaveSpectrum( parameters, windDir, new Vector2( kx * kMul, ky * kMul ) ) );

                    float re = InvRoot2 * Er * P;
                    float im = InvRoot2 * Ei * P;

                    frequencyMap[ x + y * width ] = new ComplexF( re, im );
                }
            }
        }
 /// <summary>
 /// Creates an wave animator view
 /// </summary>
 public IWaveAnimatorView CreateWaveAnimatorView( WaveAnimationParameters model )
 {
     IWaveAnimatorView view = new WaveAnimatorControl( );
     new WaveAnimatorController( m_UiProvider, view, model );
     return view;
 }