Project

General

Profile

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

examples / src / main / java / org / distorted / examples / starwars / StarWarsRenderer.java @ 107e4b72

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.MeshFlat;
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.type.Static4D;
43
import org.distorted.library.message.EffectListener;
44
import org.distorted.library.message.EffectMessage;
45
import org.distorted.library.main.Distorted;
46
import org.distorted.library.main.DistortedTexture;
47
import org.distorted.library.main.DistortedEffects;
48

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

    
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58

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

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

    
109
  private GLSurfaceView mView;
110
  private DistortedTexture mGFFATexture, mLogoTexture, mCrawlTexture, mCrawlBackgroundTexture, mStarTexture;
111
  private DistortedEffects mGFFAEffects, mLogoEffects, mCrawlEffects, mCrawlBackgroundEffects;
112
  private DistortedEffects[] mStarEffects;
113
  private DistortedNode mBackground;
114
  private DistortedScreen mScreen;
115
  private MeshFlat mQuad;
116

    
117
  private long gffaID, logoID, crawlID;
118
  private Random mRnd = new Random(0);
119
  private int mWidth, mHeight;
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
  StarWarsRenderer(GLSurfaceView v)
124
    {
125
    mView = v;
126

    
127
    mQuad = new MeshFlat(1,1);
128

    
129
    mGFFAEffects            = new DistortedEffects();
130
    mLogoEffects            = new DistortedEffects();
131
    mCrawlEffects           = new DistortedEffects();
132
    mCrawlBackgroundEffects = new DistortedEffects();
133

    
134
    if( NUM_STARS>0 )
135
      {
136
      mStarEffects = new DistortedEffects[NUM_STARS];
137
      mStarEffects[0] = new DistortedEffects();
138

    
139
      for (int i = 1; i < NUM_STARS; i++)
140
        mStarEffects[i] = new DistortedEffects(mStarEffects[0], Distorted.CLONE_VERTEX);
141
      }
142

    
143
    mScreen = new DistortedScreen();
144
    mScreen.setProjection(FOV_ANGLE, 0.02f);
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  public void onPause()
150
    {
151
    mWidth = 0;
152
    mHeight= 0;
153
    }
154

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156
   
157
  public void onDrawFrame(GL10 glUnused) 
158
    {
159
    mScreen.render(System.currentTimeMillis());
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163
    
164
  public void onSurfaceChanged(GL10 glUnused, int width, int height) 
165
    {
166
    if( mWidth!=width || mHeight!=height )  // after onPause() we get 2 calls here
167
      {
168
      mWidth = width;
169
      mHeight= height;
170

    
171
      mGFFAEffects.abortAllEffects();
172
      mLogoEffects.abortAllEffects();
173
      mCrawlEffects.abortAllEffects();
174
      mCrawlBackgroundEffects.abortAllEffects();
175

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

    
178
      mScreen.detachAll();
179
      setupScreen(width,height);
180
      mScreen.resize(width, height);
181
      }
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185
    
186
  public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
187
    {
188
    setupBitmaps();
189

    
190
    FragmentEffectAlpha.enable();
191

    
192
    try
193
      {
194
      Distorted.onCreate(mView.getContext());
195
      }
196
    catch(Exception ex)
197
      {
198
      android.util.Log.e("Star Wars", ex.getMessage() );
199
      }
200
    }
201
    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  private void setupScreen(int w, int h)
205
    {
206
    double angleA = (90.0f - FOV_ANGLE/2)*Math.PI/180;
207
    double angleB = (90.0f - FOV_ANGLE/2 +CRAWL_ANGLE)*Math.PI/180;
208

    
209
    if( mCrawlBackgroundTexture!=null ) mCrawlBackgroundTexture.markForDeletion();
210
    mCrawlBackgroundTexture = new DistortedTexture(w,(int)(h*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(w);
222
      randomY = mRnd.nextInt(h);
223
      randomS = 0.2f+ 0.8f*mRnd.nextFloat();
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 MatrixEffectMove(new Static3D(randomX,randomY,0)) );
230
      mStarEffects[i].apply( new MatrixEffectScale(randomS) );
231
      mStarEffects[i].apply( new MatrixEffectRotate(new Static1D(randomA), axis, center) );
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
    float scale = (0.5f*w/mGFFATexture.getWidth());
244
    
245
    Dynamic1D di = new Dynamic1D(6000,0.5f);
246
    di.add(new Static1D(1.0f));
247
    di.add(new Static1D(1.0f));
248
    di.add(new Static1D(0.0f));
249
    
250
    mGFFAEffects.apply( new MatrixEffectMove(new Static3D(w/5,h/3,0)) );
251
    mGFFAEffects.apply( new MatrixEffectScale(scale) );
252
    mGFFAEffects.apply( new FragmentEffectAlpha(di) );
253
      
254
    mScreen.attach(mGFFATexture, mGFFAEffects, mQuad);
255
    mGFFAEffects.registerForMessages(this);
256
    }
257
    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

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

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

    
326
    gffaID = mGFFAEffects.getID();
327
    logoID = mLogoEffects.getID();
328
    crawlID= mCrawlEffects.getID();
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
// the library sending messages to us. This is running on a library 'MessageSender' thread.
375

    
376
  public void effectMessage(final EffectMessage em, final long effectID, final long objectID)
377
    {
378
    if( em==EffectMessage.EFFECT_FINISHED )
379
      {
380
      if( objectID == gffaID )
381
        {
382
        mScreen.detach(mGFFAEffects);
383
        mGFFATexture.markForDeletion();
384

    
385
        int screenW=mScreen.getWidth();
386
        int screenH=mScreen.getHeight();
387
        
388
        int logoW = mLogoTexture.getWidth();
389
        int logoH = mLogoTexture.getHeight();
390
      
391
        int initSize= (int)(3.0f*screenW/logoW);
392
        int finaSize= (int)(0.1f*screenW/logoW);
393
      
394
        Dynamic3D di = new Dynamic3D(10000,0.5f);
395
        di.add(new Static3D(initSize,initSize,1));
396
        di.add(new Static3D(finaSize,finaSize,1));
397

    
398
        mLogoEffects.apply( new MatrixEffectMove(new Static3D(screenW/2,screenH/2,0)) );
399
        mLogoEffects.apply( new MatrixEffectScale(di) );
400
        mLogoEffects.apply( new MatrixEffectMove(new Static3D(-logoW/2,-logoH/2,0)) );
401
      
402
        mScreen.attach(mLogoTexture, mLogoEffects,mQuad);
403
        mLogoEffects.registerForMessages(this);
404
        }
405
      else if( objectID==logoID )
406
        {
407
        mScreen.detach(mLogoEffects);
408
        mLogoTexture.markForDeletion();
409
        
410
        int crawlW = mCrawlTexture.getWidth();
411
        int crawlH = mCrawlTexture.getHeight();
412
        int screenW= mScreen.getWidth();
413
        int screenH= mScreen.getHeight();
414
        int backH  = mCrawlBackgroundTexture.getHeight();
415
        float scale= (float)screenW/crawlW;
416

    
417
        mCrawlBackgroundEffects.apply( new MatrixEffectMove(new Static3D(0,screenH-backH,0)) );
418
        mCrawlBackgroundEffects.apply( new MatrixEffectRotate(new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(screenW/2,backH,0)) );
419

    
420
        final int transpDist = 5;
421
        Static4D region = new Static4D(screenW/2,(1-transpDist)*backH,transpDist*backH,transpDist*backH);
422
        mCrawlBackgroundEffects.apply( new FragmentEffectAlpha(new Static1D(1-transpDist*0.6f), region, true) );
423

    
424
        Dynamic3D di = new Dynamic3D(70000,0.5f);
425
        di.add(new Static3D(screenW/2,+backH       , 0));
426
        di.add(new Static3D(screenW/2,-scale*crawlH, 0));
427

    
428
        mCrawlEffects.apply( new MatrixEffectMove(di) );
429
        mCrawlEffects.apply( new MatrixEffectScale(new Static3D(scale,scale,scale)) );
430
        mCrawlEffects.apply( new MatrixEffectMove(new Static3D(-crawlW/2,0,0)) );
431
        
432
        mBackground = mScreen.attach(mCrawlBackgroundTexture, mCrawlBackgroundEffects,mQuad);
433
        mBackground.attach(mCrawlTexture, mCrawlEffects,mQuad);
434
        mBackground.glDisable(GLES31.GL_DEPTH_TEST);
435
        mBackground.glDepthMask(false);
436
        mCrawlEffects.registerForMessages(this);
437
        }
438
      else if( objectID==crawlID )
439
        {
440
        mScreen.detach(mBackground);
441
        mBackground.detach(mCrawlEffects);
442
        mCrawlTexture.markForDeletion();
443
        mCrawlBackgroundEffects.abortAllEffects();
444
        mCrawlBackgroundTexture.markForDeletion();
445
        }
446
      }
447
    }
448
  }
(2-2/3)