Project

General

Profile

Download (16.6 KB) Statistics
| Branch: | Revision:

examples / src / main / java / org / distorted / examples / starwars / StarWarsRenderer.java @ 698ad0a8

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.examples.starwars;
21

    
22
import java.io.IOException;
23
import java.io.InputStream;
24
import java.util.Random;
25

    
26
import javax.microedition.khronos.egl.EGLConfig;
27
import javax.microedition.khronos.opengles.GL10;
28

    
29
import org.distorted.examples.R;
30

    
31
import org.distorted.library.effect.FragmentEffectAlpha;
32
import org.distorted.library.effect.MatrixEffectMove;
33
import org.distorted.library.effect.MatrixEffectRotate;
34
import org.distorted.library.effect.MatrixEffectScale;
35
import org.distorted.library.main.DistortedNode;
36
import org.distorted.library.main.DistortedScreen;
37
import org.distorted.library.mesh.MeshQuad;
38
import org.distorted.library.type.Dynamic1D;
39
import org.distorted.library.type.Dynamic3D;
40
import org.distorted.library.type.Static1D;
41
import org.distorted.library.type.Static3D;
42
import org.distorted.library.message.EffectListener;
43
import org.distorted.library.main.DistortedLibrary;
44
import org.distorted.library.main.DistortedTexture;
45
import org.distorted.library.main.DistortedEffects;
46

    
47
import android.graphics.Bitmap;
48
import android.graphics.BitmapFactory;
49
import android.graphics.Canvas;
50
import android.graphics.Paint;
51
import android.graphics.Typeface;
52
import android.opengl.GLES31;
53
import android.opengl.GLSurfaceView;
54

    
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56

    
57
class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
58
  {
59
  private final String[] mGFFAString = 
60
         
61
            { "A long time ago, in a galaxy far,",
62
              "far away...." };                    // yes, there really was a four-dot ellipsis
63

    
64
  private final String[] mCRAWLString = 
65
      
66
            { "It is a period of civil war.",      // in the original 1977 version, there was no 
67
              "Rebel spaceships, striking",        // 'Episode IV New Hope' subtitle line before
68
              "from a hidden base, have",          // the crawl. Lets keep to the classic.
69
              "won their first victory",
70
              "against the evil Galactic",
71
              "Empire.",
72
              "",
73
              "During the battle, rebel",
74
              "spies managed to steal",
75
              "secret plans to the Empire's",
76
              "ultimate weapon, the",
77
              "DEATH STAR, an armored",
78
              "space station with enough",
79
              "power to destroy an entire",
80
              "planet.",
81
              "",
82
              "Pursued by the Empire's",
83
              "sinister agents, Princess",
84
              "Leia races home aboard her",
85
              "starship, custodian of the",
86
              "stolen plans that can save",
87
              "her people and restore",
88
              "freedom to the galaxy...." };      // four-dot.
89
   
90
  private final int NUM_STARS = 40;
91
   
92
  private final int CRAWL_COLOR = 0xffffe81f;
93
  private final int GFFA_COLOR  = 0xff0000ff;
94
  private final int FONT_HEIGHT      = 40;
95
  private final int VERTICAL_SPACING = 10;
96
  private final String CRAWL_TYPEFACE = "News Gothic";
97
   
98
  private final int CRAWL_WIDTH = 500;
99
  private final int CRAWL_HEIGHT= (FONT_HEIGHT+VERTICAL_SPACING)*(mCRAWLString.length+1);
100
   
101
  private final int GFFA_WIDTH = 600;
102
  private final int GFFA_HEIGHT= (FONT_HEIGHT+VERTICAL_SPACING)*(mGFFAString.length+1);
103
   
104
  private final float CRAWL_ANGLE = -30.0f;
105
  private final float FOV_ANGLE   =  60.0f;
106

    
107
  private GLSurfaceView mView;
108
  private DistortedTexture mGFFATexture, mLogoTexture, mCrawlTexture, mCrawlBackgroundTexture, mStarTexture;
109
  private DistortedEffects mGFFAEffects, mLogoEffects, mCrawlEffects, mCrawlBackgroundEffects;
110
  private DistortedEffects[] mStarEffects;
111
  private DistortedNode mBackground;
112
  private DistortedScreen mScreen;
113
  private MeshQuad mGFFAQuad, mCrawlQuad, mCrawlBackgroundQuad, mLogoQuad, mStarQuad;
114

    
115
  private long alphaEffectID, scaleEffectID, moveEffectID;
116
  private Random mRnd = new Random(0);
117
  private int mWidth, mHeight;
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

    
121
  StarWarsRenderer(GLSurfaceView v)
122
    {
123
    mView = v;
124

    
125
    mGFFAQuad            = new MeshQuad();
126
    mStarQuad            = new MeshQuad();
127
    mCrawlQuad           = new MeshQuad();
128
    mCrawlBackgroundQuad = new MeshQuad();
129
    mLogoQuad            = new MeshQuad();
130

    
131
    mGFFAQuad.setStretch(GFFA_WIDTH,GFFA_HEIGHT,0);
132
    mCrawlQuad.setStretch(CRAWL_WIDTH,CRAWL_HEIGHT,0);
133

    
134
    mGFFAEffects            = new DistortedEffects();
135
    mLogoEffects            = new DistortedEffects();
136
    mCrawlEffects           = new DistortedEffects();
137
    mCrawlBackgroundEffects = new DistortedEffects();
138

    
139
    if( NUM_STARS>0 )
140
      {
141
      mStarEffects = new DistortedEffects[NUM_STARS];
142
      mStarEffects[0] = new DistortedEffects();
143

    
144
      for (int i = 1; i < NUM_STARS; i++)
145
        mStarEffects[i] = new DistortedEffects(mStarEffects[0], DistortedLibrary.CLONE_VERTEX);
146
      }
147

    
148
    mScreen = new DistortedScreen();
149
    mScreen.setProjection(FOV_ANGLE, 0.02f);
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

    
154
  public void onPause()
155
    {
156
    mWidth = 0;
157
    mHeight= 0;
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161
   
162
  public void onDrawFrame(GL10 glUnused) 
163
    {
164
    mScreen.render(System.currentTimeMillis());
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168
    
169
  public void onSurfaceChanged(GL10 glUnused, int width, int height) 
170
    {
171
    if( mWidth!=width || mHeight!=height )  // after onPause() we get 2 calls here
172
      {
173
      mWidth = width;
174
      mHeight= height;
175

    
176
      mGFFAEffects.abortAllEffects();
177
      mLogoEffects.abortAllEffects();
178
      mCrawlEffects.abortAllEffects();
179
      mCrawlBackgroundEffects.abortAllEffects();
180

    
181
      for(int i=0; i<NUM_STARS; i++) mStarEffects[i].abortAllEffects();
182

    
183
      mScreen.detachAll();
184
      setupScreen(width,height);
185
      mScreen.resize(width, height);
186
      }
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190
    
191
  public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
192
    {
193
    setupBitmaps();
194

    
195
    FragmentEffectAlpha.enable();
196

    
197
    try
198
      {
199
      DistortedLibrary.onCreate(mView.getContext());
200
      }
201
    catch(Exception ex)
202
      {
203
      android.util.Log.e("Star Wars", ex.getMessage() );
204
      }
205
    }
206
    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  private void setupScreen(int w, int h)
210
    {
211
    double angleA = (90.0f - FOV_ANGLE/2)*Math.PI/180;
212
    double angleB = (90.0f - FOV_ANGLE/2 +CRAWL_ANGLE)*Math.PI/180;
213

    
214
    if( mCrawlBackgroundTexture!=null ) mCrawlBackgroundTexture.markForDeletion();
215
    mCrawlBackgroundTexture = new DistortedTexture();
216

    
217
    mCrawlBackgroundQuad.setStretch(w,(int)(h*Math.sin(angleA)/Math.sin(angleB)),0);
218

    
219
    int randomA, randomX, randomY, randomTime;
220
    float randomS, randomAlpha1, randomAlpha2;
221
       
222
    Static3D center = new Static3D(0,0,0);
223
    Static3D axis   = new Static3D(0,0,1);
224
    Static1D alphaNoise = new Static1D(0.4f);
225

    
226
    for(int i=0; i<NUM_STARS; i++)
227
      {
228
      randomX = mRnd.nextInt(w);
229
      randomY = mRnd.nextInt(h);
230
      randomS = 0.2f+ 0.8f*mRnd.nextFloat();
231
      randomA = (int)(180*mRnd.nextFloat());
232
      randomAlpha1 = 0.2f + 0.8f*mRnd.nextFloat();
233
      randomAlpha2 = 0.8f + 0.2f*mRnd.nextFloat();
234
      randomTime = 500+mRnd.nextInt(2000);
235

    
236
      mStarEffects[i].apply( new MatrixEffectRotate(new Static1D(randomA), axis, center) );
237
      mStarEffects[i].apply( new MatrixEffectScale(randomS) );
238
      mStarEffects[i].apply( new MatrixEffectMove(new Static3D(randomX,randomY,0)) );
239

    
240
      Dynamic1D di = new Dynamic1D(randomTime,0.0f);
241
      di.setNoise(alphaNoise);
242
      di.add(new Static1D(randomAlpha1));
243
      di.add(new Static1D(randomAlpha2));
244
      
245
      mStarEffects[i].apply( new FragmentEffectAlpha(di) );
246
      
247
      mScreen.attach(mStarTexture, mStarEffects[i], mStarQuad);
248
      }
249
      
250
    float scale = (0.5f*w/mGFFAQuad.getStretchX());
251
    
252
    Dynamic1D di = new Dynamic1D(6000,0.5f);
253
    di.add(new Static1D(1.0f));
254
    di.add(new Static1D(1.0f));
255
    di.add(new Static1D(0.0f));
256

    
257
    FragmentEffectAlpha alpha = new FragmentEffectAlpha(di);
258
    alpha.notifyWhenFinished(this);
259
    alphaEffectID = alpha.getID();
260

    
261
    mGFFAEffects.apply( new MatrixEffectScale(scale) );
262
    mGFFAEffects.apply( new MatrixEffectMove(new Static3D(w/5,2*h/3,0)) );
263
    mGFFAEffects.apply( alpha );
264
      
265
    mScreen.attach(mGFFATexture, mGFFAEffects, mGFFAQuad);
266
    }
267
    
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

    
270
  private void setupBitmaps()
271
    {
272
    InputStream is1 = mView.getContext().getResources().openRawResource(R.raw.starwars);
273
    InputStream is2 = mView.getContext().getResources().openRawResource(R.raw.star);
274
    
275
    Bitmap bitmapStar, bitmapGFFA, bitmapLogo, bitmapText;
276
      
277
    try 
278
      {
279
      bitmapLogo = BitmapFactory.decodeStream(is1);
280
      bitmapStar = BitmapFactory.decodeStream(is2);
281
      } 
282
    finally 
283
      {
284
      try 
285
        {
286
        is1.close();
287
        is2.close();
288
        } 
289
      catch(IOException e) { }
290
      } 
291
      
292
    Paint paint = new Paint();
293
    paint.setAntiAlias(true);
294
    paint.setTextAlign(Paint.Align.LEFT);
295
    paint.setTextSize(FONT_HEIGHT);
296
    paint.setColor(GFFA_COLOR);
297
      
298
    Typeface tf = Typeface.create(CRAWL_TYPEFACE, Typeface.BOLD);
299
    paint.setTypeface(tf);     
300
 
301
    ///// create GFFA ///////////////////
302
    if( mGFFATexture==null ) mGFFATexture  = new DistortedTexture();
303
    bitmapGFFA = Bitmap.createBitmap(GFFA_WIDTH,GFFA_HEIGHT,Bitmap.Config.ARGB_8888);
304
    bitmapGFFA.eraseColor(0x00000000);
305
    Canvas gffaCanvas = new Canvas(bitmapGFFA);
306
      
307
    for(int i=0; i<mGFFAString.length; i++)
308
      {
309
      gffaCanvas.drawText(mGFFAString[i], 0, (i+1)*(FONT_HEIGHT+VERTICAL_SPACING), paint);  
310
      }
311
  
312
    mGFFATexture.setTexture(bitmapGFFA);
313
      
314
    ///// create Logo ///////////////////
315
    mLogoQuad.setStretch(bitmapLogo.getWidth(),bitmapLogo.getHeight(),0);
316
    if( mLogoTexture==null ) mLogoTexture  = new DistortedTexture();
317
    mLogoTexture.setTexture(bitmapLogo);
318

    
319
    ///// create CRAWL //////////////////
320
    if( mCrawlTexture==null ) mCrawlTexture = new DistortedTexture();
321
    bitmapText = Bitmap.createBitmap(CRAWL_WIDTH,CRAWL_HEIGHT,Bitmap.Config.ARGB_8888);
322
    bitmapText.eraseColor(0x00000000);
323
    Canvas textCanvas = new Canvas(bitmapText);
324
    paint.setColor(CRAWL_COLOR);
325
  
326
    for(int i=0; i<mCRAWLString.length; i++)
327
      {
328
      displayJustified(mCRAWLString[i], 0, (i+1)*(FONT_HEIGHT+VERTICAL_SPACING), CRAWL_WIDTH, textCanvas, paint);  
329
      }
330
      
331
    mCrawlTexture.setTexture(bitmapText);
332
      
333
    ///// create Stars ///////////////////
334
    mStarQuad.setStretch(bitmapStar.getWidth(),bitmapStar.getHeight(),0);
335
    if( mStarTexture==null ) mStarTexture = new DistortedTexture();
336
    mStarTexture.setTexture(bitmapStar);
337
    }
338
 
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340

    
341
  private void displayJustified(String str, int x, int y, int length, Canvas c, Paint paint)
342
    { 
343
    int len       = str.length();
344
    int numspaces = retNumSpaces(str);
345
    
346
    if( len>0 && str.charAt(len-1) == ' ' ) numspaces--;
347

    
348
    float left=x,w = (numspaces>0 ? (length-paint.measureText(str))/numspaces : 0);
349
    String tmp;
350
    int begin,end=0;
351

    
352
    while( end<len )
353
      {
354
      begin=end;
355
      end = str.indexOf(' ', begin)+1;
356
      if( end<=0 ) end = len;
357

    
358
      tmp = str.substring(begin,end);
359
      c.drawText( tmp, left, y, paint);
360
      left+= (paint.measureText(tmp)+w);
361
      }  
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365
   
366
  private int retNumSpaces(String str)
367
    {
368
    int begin=0, ret=0;
369

    
370
    while( true )
371
      {
372
      begin = str.indexOf(' ', begin) +1;
373

    
374
      if( begin>0 ) ret++;
375
      else break;
376
      }
377

    
378
    return ret;
379
    }
380
    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  public void effectFinished(final long effectID)
384
    {
385
    if( effectID == alphaEffectID )
386
      {
387
      mScreen.detach(mGFFAEffects);
388
      mGFFATexture.markForDeletion();
389

    
390
      int screenW=mScreen.getWidth();
391
      int screenH=mScreen.getHeight();
392
        
393
      float logoW = mLogoQuad.getStretchX();
394
      float logoH = mLogoQuad.getStretchY();
395
      
396
      int initSize= (int)(3.0f*screenW/logoW);
397
      int finaSize= (int)(0.1f*screenW/logoW);
398
      
399
      Dynamic3D di = new Dynamic3D(10000,0.5f);
400
      di.add(new Static3D(initSize,initSize,1));
401
      di.add(new Static3D(finaSize,finaSize,1));
402
      MatrixEffectScale scale = new MatrixEffectScale(di);
403
      scale.notifyWhenFinished(this);
404
      scaleEffectID = scale.getID();
405

    
406
      mLogoEffects.apply( new MatrixEffectMove(new Static3D(-logoW/2,-logoH/2,0)) );
407
      mLogoEffects.apply( scale );
408
      mLogoEffects.apply( new MatrixEffectMove(new Static3D(screenW/2,screenH/2,0)) );
409

    
410
      mScreen.attach(mLogoTexture, mLogoEffects, mLogoQuad);
411
      }
412
    else if( effectID == scaleEffectID )
413
      {
414
      mScreen.detach(mLogoEffects);
415
      mLogoTexture.markForDeletion();
416
        
417
      float crawlW = mCrawlQuad.getStretchX();
418
      float crawlH = mCrawlQuad.getStretchY();
419
      float screenW= mScreen.getWidth();
420
      float backH  = mCrawlBackgroundQuad.getStretchY();
421
      float scale  = screenW/crawlW;
422

    
423
      mCrawlBackgroundEffects.apply( new MatrixEffectRotate(new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(screenW/2,0,0)) );
424

    
425
      final int transpDist = 5;
426
      Static3D center = new Static3D( screenW/2 , transpDist*backH , 0 );
427
      Static3D region = new Static3D( transpDist*backH , transpDist*backH , transpDist*backH );
428
      mCrawlBackgroundEffects.apply( new FragmentEffectAlpha(new Static1D(1-transpDist*0.6f), center, region, true) );
429

    
430
      Dynamic3D di = new Dynamic3D(70000,0.5f);
431
      di.add(new Static3D(screenW/2,-scale*crawlH/2        , 0));
432
      di.add(new Static3D(screenW/2,+scale*crawlH/2 + backH, 0));
433
      MatrixEffectMove move = new MatrixEffectMove(di);
434
      move.notifyWhenFinished(this);
435
      moveEffectID = move.getID();
436

    
437
      mCrawlEffects.apply( new MatrixEffectMove(new Static3D(-crawlW/2,-crawlH/2,0)) );
438
      mCrawlEffects.apply( new MatrixEffectScale(new Static3D(scale,scale,scale)) );
439
      mCrawlEffects.apply( move );
440

    
441
      mBackground = mScreen.attach(mCrawlBackgroundTexture, mCrawlBackgroundEffects, mCrawlBackgroundQuad);
442
      mBackground.attach(mCrawlTexture, mCrawlEffects, mCrawlQuad);
443
      mBackground.glDisable(GLES31.GL_DEPTH_TEST);
444
      mBackground.glDepthMask(false);
445
      }
446
    else if( effectID == moveEffectID )
447
      {
448
      mScreen.detach(mBackground);
449
      mBackground.detach(mCrawlEffects);
450
      mCrawlTexture.markForDeletion();
451
      mCrawlBackgroundEffects.abortAllEffects();
452
      mCrawlBackgroundTexture.markForDeletion();
453
      }
454
    }
455
  }
(2-2/3)