commit 318dd77baf506568583b93d16b811e51c750b902
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Jan 24 22:22:41 2019 +0000

    Some improvements to the Wind app - still does not look very realistic though :(

diff --git a/src/main/java/org/distorted/examples/wind/WindActivity.java b/src/main/java/org/distorted/examples/wind/WindActivity.java
index d4a93ee..bbb9253 100644
--- a/src/main/java/org/distorted/examples/wind/WindActivity.java
+++ b/src/main/java/org/distorted/examples/wind/WindActivity.java
@@ -49,8 +49,6 @@ public class WindActivity extends Activity implements OnSeekBarChangeListener
       windText = findViewById(R.id.windText);
      
       bar.setProgress(50);
-      
-      windText.setText(getString(R.string.wind_placeholder,50));
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/wind/WindEffectsManager.java b/src/main/java/org/distorted/examples/wind/WindEffectsManager.java
index b42e4e8..332c5ed 100644
--- a/src/main/java/org/distorted/examples/wind/WindEffectsManager.java
+++ b/src/main/java/org/distorted/examples/wind/WindEffectsManager.java
@@ -35,6 +35,12 @@ import org.distorted.library.type.Static5D;
 
 class WindEffectsManager
   {
+  private static final long TIME_TO_GET_UP    = 400; // time it takes for the max wind to
+                                                     // make the flag horizontal (milliseconds)
+  private static final long TIME_TO_FALL_DOWN =2000; // time it takes for the flag to
+                                                     // fall back down if no wind (milliseconds)
+  private long lastTime;
+  private float mWind;
   private int mHeight, mWidth;
 
   private Static3D  shearFactor;
@@ -46,11 +52,15 @@ class WindEffectsManager
   private Dynamic5D windDynamic2;
   private Static5D  windFactor31, windFactor32;
   private Dynamic5D windDynamic3;
+  private Static5D  windFactor41, windFactor42;
+  private Dynamic5D windDynamic4;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   WindEffectsManager(DistortedTexture texture)
     {
+    lastTime = 0;
+
     mHeight = texture.getHeight();
     mWidth  = texture.getWidth();
 
@@ -81,17 +91,26 @@ class WindEffectsManager
     windDynamic3.add(windFactor32);
     windDynamic3.setMode(Dynamic.MODE_JUMP);
     windDynamic3.setAccessMode(Dynamic.ACCESS_SEQUENTIAL);
+
+    windFactor41 = new Static5D(mHeight/10,mHeight/5,-180,  0,  0);
+    windFactor42 = new Static5D(mHeight/10,mHeight/5,+180,  0,  0);
+    windDynamic4 = new Dynamic5D(1000,0.0f);
+    windDynamic4.add(windFactor41);
+    windDynamic4.add(windFactor42);
+    windDynamic4.setMode(Dynamic.MODE_JUMP);
+    windDynamic4.setAccessMode(Dynamic.ACCESS_SEQUENTIAL);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  void apply(DistortedEffects effects, int wind)
+  void apply(DistortedEffects effects)
     {
-    Static3D midLeft = new Static3D(0,mHeight/2,0);
-    Static3D midRight = new Static3D(mWidth,mHeight/2,0);
+    Static3D midLeft    = new Static3D(0,mHeight/2,0);
+    Static3D midRight   = new Static3D(mWidth,mHeight/2,0);
+    Static3D tadRight   = new Static3D(3*mWidth/4,mHeight/2,0);
     Static4D windRegion = new Static4D(0,0,0,mHeight);
 
-    setWind(wind);
+    setWind(0);
 
     effects.apply( new MatrixEffectShear(shearFactor,midLeft) );
     effects.apply( new MatrixEffectScale(scaleFactor) );
@@ -99,26 +118,71 @@ class WindEffectsManager
     effects.apply( new VertexEffectWave(windDynamic1, midRight, windRegion) );
     effects.apply( new VertexEffectWave(windDynamic2, midRight, windRegion) );
     effects.apply( new VertexEffectWave(windDynamic3, midRight, windRegion) );
+    effects.apply( new VertexEffectWave(windDynamic4, tadRight, windRegion) );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  synchronized void setWind(int wind)
+  private void setWind(int wind)
     {
-    float tanAngle = (wind-50)/50.0f;
+    mWind = wind;
 
+    float tanAngle = (wind-50)/50.0f;
     shearFactor.set2(tanAngle);
     scaleFactor.set1(1/(float)Math.sqrt(1+tanAngle*tanAngle));
-    windDynamic1.setDuration( wind > 0 ? 100000/wind : Long.MAX_VALUE);
-    windDynamic2.setDuration( wind > 0 ?  80000/wind : Long.MAX_VALUE);
-    windDynamic3.setDuration( wind > 0 ? 100000/wind : Long.MAX_VALUE);
 
-    float waveA = (mHeight/(20.0f-0.15f*wind));
-    windFactor21.set1(waveA);
-    windFactor22.set1(waveA);
+    windDynamic1.setDuration( wind > 0 ? 900 + 10000/wind : Long.MAX_VALUE);
+    windDynamic2.setDuration( wind > 0 ? 720 +  8000/wind : Long.MAX_VALUE);
+    windDynamic3.setDuration( wind > 0 ? 900 + 10000/wind : Long.MAX_VALUE);
+
+    float wave2 = mHeight*( 0.05f + 0.002f*wind);
+    windFactor21.set1(wave2);
+    windFactor22.set1(wave2);
+
+    float wave3 = (mHeight/(wind+5.0f));
+    windFactor31.set1(wave3);
+    windFactor32.set1(wave3);
+
+    float wave4 = (mHeight*(wind*(100-wind)/50000.0f));
+    windFactor41.set1(wave4);
+    windFactor42.set1(wave4);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  synchronized void increaseWind(long currTime)
+    {
+    if( lastTime>0 )
+      {
+      long diff = currTime-lastTime;
+      float diffWind = (100.0f*diff/TIME_TO_GET_UP);
+
+      mWind += diffWind;
+      if( mWind>100.0f ) mWind=100.0f;
+
+      setWind( (int)mWind );
+      }
+
+    lastTime = currTime;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  synchronized void decreaseWind(long currTime)
+    {
+    if( lastTime>0 )
+      {
+      long diff = currTime-lastTime;
+      float diffWind = (100.0f*diff/TIME_TO_FALL_DOWN);
+
+      mWind -= diffWind;
+      if( mWind<0.0f ) mWind=0.0f;
 
-    float waveB = (mHeight/(wind+5.0f));
-    windFactor31.set1(waveB);
-    windFactor32.set1(waveB);
+      setWind( (int)mWind );
+      }
+
+    lastTime = currTime;
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
   }
diff --git a/src/main/java/org/distorted/examples/wind/WindGust.java b/src/main/java/org/distorted/examples/wind/WindGust.java
new file mode 100644
index 0000000..9a91c09
--- /dev/null
+++ b/src/main/java/org/distorted/examples/wind/WindGust.java
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2019 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted is free software: you can redistribute it and/or modify                             //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Distorted is distributed in the hope that it will be useful,                                  //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.examples.wind;
+
+import java.util.Random;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class WindGust
+  {
+  private static final long TIME_PERIOD = 1000;
+  private int mAvgWind;
+  private boolean mBlowingNow;
+  private long mLastTime;
+  private static Random mRnd = new Random();
+
+  WindGust()
+    {
+    mAvgWind = 0;
+    mBlowingNow = false;
+    mLastTime = 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void setAverageWind(int wind)
+    {
+    mAvgWind = wind;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  boolean isWindBlowingNow(long currTime)
+    {
+    if( mLastTime>0 )
+      {
+      int lastPeriod = (int)(mLastTime/TIME_PERIOD);
+      int currPeriod = (int)( currTime/TIME_PERIOD);
+
+      if( currPeriod>lastPeriod ) mBlowingNow=(mRnd.nextInt(100)<=mAvgWind);
+      }
+
+    mLastTime = currTime;
+
+    return mBlowingNow;
+    }
+  }
diff --git a/src/main/java/org/distorted/examples/wind/WindRenderer.java b/src/main/java/org/distorted/examples/wind/WindRenderer.java
index 2830c91..039509e 100644
--- a/src/main/java/org/distorted/examples/wind/WindRenderer.java
+++ b/src/main/java/org/distorted/examples/wind/WindRenderer.java
@@ -51,9 +51,9 @@ class WindRenderer implements GLSurfaceView.Renderer
    private DistortedTexture mTexture;
    private DistortedScreen mScreen;
    private WindEffectsManager mManager;
+   private WindGust mGust;
    private Static3D mMove, mScale;
    private int mObjWidth, mObjHeight;
-   private int mWind;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -63,6 +63,7 @@ class WindRenderer implements GLSurfaceView.Renderer
 
       mTexture = new DistortedTexture(50,30);
       mManager = new WindEffectsManager(mTexture);
+      mGust    = new WindGust();
       mScreen  = new DistortedScreen();
 
       DistortedEffects effects = new DistortedEffects();
@@ -82,30 +83,36 @@ class WindRenderer implements GLSurfaceView.Renderer
       Static3D center= new Static3D(0,mObjHeight/2,0);
 
       effects.apply( new MatrixEffectRotate(angle, axis, center) );
-      mManager.apply(effects,mWind);
+      mManager.apply(effects);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    void setWind(int wind)
       {
-      mWind = wind;
-      mManager.setWind(mWind);
+      mGust.setAverageWind(wind);
       }
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
    public void onDrawFrame(GL10 glUnused) 
       {
-      mScreen.render( System.currentTimeMillis() );
+      long time = System.currentTimeMillis();
+
+      if( mGust.isWindBlowingNow(time) ) mManager.increaseWind(time);
+      else                               mManager.decreaseWind(time);
+
+      mScreen.render(time);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      float factor = ( (float)(width<height? width:height) )/(mObjHeight + 1.4f*mObjWidth);
-      mMove.set( factor*mObjHeight*0.58f , height - factor*mObjHeight*1.08f , 0 );
+      int min = width<height? width:height;
+
+      float factor = ((float)min)/(mObjHeight + 1.4f*mObjWidth);
+      mMove.set( factor*mObjHeight*0.58f +(width-min)/2, height - factor*mObjHeight*1.08f -(height-min)/2, 0 );
       mScale.set(factor,factor,factor);
       mScreen.resize(width, height);
       }
