Project

General

Profile

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

examples / src / main / java / org / distorted / examples / starwars / StarWarsRenderer.java @ dc10a48d

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.app.ActivityManager;
48
import android.content.Context;
49
import android.content.pm.ConfigurationInfo;
50
import android.content.res.Resources;
51
import android.graphics.Bitmap;
52
import android.graphics.BitmapFactory;
53
import android.graphics.Canvas;
54
import android.graphics.Paint;
55
import android.graphics.Typeface;
56
import android.opengl.GLES31;
57
import android.opengl.GLSurfaceView;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

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

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

    
111
  private final GLSurfaceView mView;
112
  private final DistortedEffects mGFFAEffects, mLogoEffects, mCrawlEffects, mCrawlBackgroundEffects;
113
  private final DistortedEffects[] mStarEffects;
114
  private final DistortedScreen mScreen;
115
  private final MeshQuad mQuad;
116
  private final Random mRnd = new Random(0);
117
  private final Resources mResources;
118

    
119
  private DistortedTexture mGFFATexture, mLogoTexture, mCrawlTexture, mCrawlBackgroundTexture, mStarTexture;
120
  private DistortedNode mBackground;
121
  private long alphaEffectID, scaleEffectID, moveEffectID;
122
  private int mWidth, mHeight;
123
  private float mLogoRatio;
124
  private int mCrawlBackgroundW, mCrawlBackgroundH;
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127

    
128
  StarWarsRenderer(GLSurfaceView v)
129
    {
130
    mView = v;
131
    mResources = v.getResources();
132

    
133
    mQuad = new MeshQuad();
134

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

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

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

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

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

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

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

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

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

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

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

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191
    
192
  public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
193
    {
194
    setupBitmaps();
195
    FragmentEffectAlpha.enable();
196
    DistortedLibrary.onSurfaceCreated(this);
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
  private void setupScreen(int scrW, int scrH)
202
    {
203
    double angleA = (90.0f - FOV_ANGLE/2              ) * Math.PI/180;
204
    double angleB = (90.0f - FOV_ANGLE/2 + CRAWL_ANGLE) * Math.PI/180;
205

    
206
    if( mCrawlBackgroundTexture!=null ) mCrawlBackgroundTexture.markForDeletion();
207
    mCrawlBackgroundTexture = new DistortedTexture();
208

    
209
    mCrawlBackgroundW = scrW;
210
    mCrawlBackgroundH = (int)(scrH*Math.sin(angleA)/Math.sin(angleB));
211

    
212
    int randomA, randomX, randomY, randomTime;
213
    float randomS, randomAlpha1, randomAlpha2;
214
       
215
    Static3D center = new Static3D(0,0,0);
216
    Static3D axis   = new Static3D(0,0,1);
217
    Static1D alphaNoise = new Static1D(0.4f);
218

    
219
    for(int i=0; i<NUM_STARS; i++)
220
      {
221
      randomX = mRnd.nextInt(scrW) - scrW/2;
222
      randomY = mRnd.nextInt(scrH) - scrH/2;
223
      randomS = (0.2f+ 0.8f*mRnd.nextFloat())*20;
224
      randomA = (int)(180*mRnd.nextFloat());
225
      randomAlpha1 = 0.2f + 0.8f*mRnd.nextFloat();
226
      randomAlpha2 = 0.8f + 0.2f*mRnd.nextFloat();
227
      randomTime = 500+mRnd.nextInt(2000);
228

    
229
      mStarEffects[i].apply( new MatrixEffectRotate(new Static1D(randomA), axis, center) );
230
      mStarEffects[i].apply( new MatrixEffectScale(randomS) );
231
      mStarEffects[i].apply( new MatrixEffectMove(new Static3D(randomX,randomY,0)) );
232

    
233
      Dynamic1D di = new Dynamic1D(randomTime,0.0f);
234
      di.setNoise(alphaNoise);
235
      di.add(new Static1D(randomAlpha1));
236
      di.add(new Static1D(randomAlpha2));
237
      
238
      mStarEffects[i].apply( new FragmentEffectAlpha(di) );
239
      
240
      mScreen.attach(mStarTexture, mStarEffects[i], mQuad);
241
      }
242

    
243
    Dynamic1D di = new Dynamic1D(6000,0.5f);
244
    di.add(new Static1D(1.0f));
245
    di.add(new Static1D(1.0f));
246
    di.add(new Static1D(0.0f));
247

    
248
    FragmentEffectAlpha alpha = new FragmentEffectAlpha(di);
249
    alpha.notifyWhenFinished(this);
250
    alphaEffectID = alpha.getID();
251

    
252
    Static3D scale = new Static3D(0.5f*scrW, 0.5f*scrW * GFFA_HEIGHT / GFFA_WIDTH, 1);
253

    
254
    mGFFAEffects.apply( new MatrixEffectScale(scale) );
255
    mGFFAEffects.apply( new MatrixEffectMove(new Static3D(-scrW/3 + GFFA_WIDTH/2 ,scrH/6,0)) );
256
    mGFFAEffects.apply( alpha );
257
      
258
    mScreen.attach(mGFFATexture, mGFFAEffects, mQuad);
259
    }
260
    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

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

    
312
    ///// create CRAWL //////////////////
313
    if( mCrawlTexture==null ) mCrawlTexture = new DistortedTexture();
314
    bitmapText = Bitmap.createBitmap(CRAWL_WIDTH,CRAWL_HEIGHT,Bitmap.Config.ARGB_8888);
315
    bitmapText.eraseColor(0x00000000);
316
    Canvas textCanvas = new Canvas(bitmapText);
317
    paint.setColor(CRAWL_COLOR);
318
  
319
    for(int i=0; i<mCRAWLString.length; i++)
320
      {
321
      displayJustified(mCRAWLString[i], 0, (i+1)*(FONT_HEIGHT+VERTICAL_SPACING), CRAWL_WIDTH, textCanvas, paint);  
322
      }
323
      
324
    mCrawlTexture.setTexture(bitmapText);
325
      
326
    ///// create Stars ///////////////////
327
    if( mStarTexture==null ) mStarTexture = new DistortedTexture();
328
    mStarTexture.setTexture(bitmapStar);
329
    }
330
 
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
  private void displayJustified(String str, int x, int y, int length, Canvas c, Paint paint)
334
    { 
335
    int len       = str.length();
336
    int numspaces = retNumSpaces(str);
337
    
338
    if( len>0 && str.charAt(len-1) == ' ' ) numspaces--;
339

    
340
    float left=x,w = (numspaces>0 ? (length-paint.measureText(str))/numspaces : 0);
341
    String tmp;
342
    int begin,end=0;
343

    
344
    while( end<len )
345
      {
346
      begin=end;
347
      end = str.indexOf(' ', begin)+1;
348
      if( end<=0 ) end = len;
349

    
350
      tmp = str.substring(begin,end);
351
      c.drawText( tmp, left, y, paint);
352
      left+= (paint.measureText(tmp)+w);
353
      }  
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357
   
358
  private int retNumSpaces(String str)
359
    {
360
    int begin=0, ret=0;
361

    
362
    while( true )
363
      {
364
      begin = str.indexOf(' ', begin) +1;
365

    
366
      if( begin>0 ) ret++;
367
      else break;
368
      }
369

    
370
    return ret;
371
    }
372
    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
  public void effectFinished(final long effectID)
376
    {
377
    if( effectID == alphaEffectID )
378
      {
379
      mScreen.detach(mGFFAEffects);
380
      mGFFATexture.markForDeletion();
381

    
382
      int screenW = mScreen.getWidth();
383
      int initSize= (int)(3.00f*screenW);
384
      int finaSize= (int)(0.01f*screenW);
385
      
386
      Dynamic3D di = new Dynamic3D(10000,0.5f);
387
      di.add(new Static3D(initSize,initSize/mLogoRatio,1));
388
      di.add(new Static3D(finaSize,finaSize/mLogoRatio,1));
389
      MatrixEffectScale scale = new MatrixEffectScale(di);
390
      scale.notifyWhenFinished(this);
391
      scaleEffectID = scale.getID();
392
      mLogoEffects.apply( scale );
393
      mScreen.attach(mLogoTexture, mLogoEffects, mQuad);
394
      }
395
    else if( effectID == scaleEffectID )
396
      {
397
      mScreen.detach(mLogoEffects);
398
      mLogoTexture.markForDeletion();
399

    
400
      float scale = mCrawlBackgroundW/CRAWL_WIDTH;
401

    
402
      mCrawlBackgroundEffects.apply( new MatrixEffectScale( new Static3D(mCrawlBackgroundW, mCrawlBackgroundH, 1) ) );
403
      mCrawlBackgroundEffects.apply( new MatrixEffectRotate(new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(0,-mCrawlBackgroundH/2,0)) );
404
      mCrawlBackgroundEffects.apply( new MatrixEffectMove(new Static3D( 0, (mCrawlBackgroundH-mHeight)/2, 0)) );
405

    
406
      final float transpDist = 5;
407
      Static3D center = new Static3D( 0, transpDist-0.5f, 0 );
408
      Static3D region = new Static3D( transpDist, transpDist, transpDist );
409
      mCrawlBackgroundEffects.apply( new FragmentEffectAlpha(new Static1D(1-transpDist*0.6f), center, region, true) );
410

    
411
      Dynamic3D di = new Dynamic3D(70000,0.5f);
412
      di.add(new Static3D(0, -(scale*CRAWL_HEIGHT+mCrawlBackgroundH)/2, 0));
413
      di.add(new Static3D(0, +(scale*CRAWL_HEIGHT+mCrawlBackgroundH)/2, 0));
414
      MatrixEffectMove move = new MatrixEffectMove(di);
415
      move.notifyWhenFinished(this);
416
      moveEffectID = move.getID();
417

    
418
      mCrawlEffects.apply( new MatrixEffectScale(new Static3D(scale*CRAWL_WIDTH,scale*CRAWL_HEIGHT,1)) );
419
      mCrawlEffects.apply( move );
420

    
421
      mBackground = mScreen.attach(mCrawlBackgroundTexture, mCrawlBackgroundEffects, mQuad);
422
      mBackground.resizeFBO(mCrawlBackgroundW,mCrawlBackgroundH);
423
      mBackground.attach(mCrawlTexture, mCrawlEffects, mQuad);
424
      mBackground.glDisable(GLES31.GL_DEPTH_TEST);
425
      mBackground.glDepthMask(false);
426
      }
427
    else if( effectID == moveEffectID )
428
      {
429
      mScreen.detach(mBackground);
430
      mBackground.detach(mCrawlEffects);
431
      mCrawlTexture.markForDeletion();
432
      mCrawlBackgroundEffects.abortAllEffects();
433
      mCrawlBackgroundTexture.markForDeletion();
434
      }
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  public void distortedException(Exception ex)
440
    {
441
    android.util.Log.e("StarWars", ex.getMessage() );
442
    }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
  public int openGlVersion()
447
    {
448
    Context context = mView.getContext();
449
    final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
450
    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
451
    int glESversion = configurationInfo.reqGlEsVersion;
452
    int major = glESversion >> 16;
453
    int minor = glESversion & 0xff;
454

    
455
    return 100*major + 10*minor;
456
    }
457

    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459

    
460
  public InputStream localFile(int fileID)
461
    {
462
    return mResources.openRawResource(fileID);
463
    }
464

    
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466

    
467
  public void logMessage(String message)
468
    {
469
    android.util.Log.e("StarWars", message );
470
    }
471
  }
(2-2/3)