/// <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; }