Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / MeshFileRenderer.java @ df7b70a0

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.meshfile;
21

    
22
import android.content.Context;
23
import android.content.res.Resources;
24
import android.graphics.Bitmap;
25
import android.graphics.Canvas;
26
import android.graphics.Paint;
27
import android.opengl.GLSurfaceView;
28

    
29
import org.distorted.examples.R;
30
import org.distorted.library.effect.EffectType;
31
import org.distorted.library.effect.MatrixEffectQuaternion;
32
import org.distorted.library.effect.MatrixEffectScale;
33
import org.distorted.library.effect.VertexEffectDeform;
34
import org.distorted.library.effect.VertexEffectDisappear;
35
import org.distorted.library.effect.VertexEffectMove;
36
import org.distorted.library.effect.VertexEffectRotate;
37
import org.distorted.library.effect.VertexEffectSink;
38
import org.distorted.library.main.DistortedEffects;
39
import org.distorted.library.main.DistortedLibrary;
40
import org.distorted.library.main.DistortedScreen;
41
import org.distorted.library.main.DistortedTexture;
42
import org.distorted.library.mesh.MeshBase;
43
import org.distorted.library.mesh.MeshFile;
44
import org.distorted.library.mesh.MeshJoined;
45
import org.distorted.library.mesh.MeshPolygon;
46
import org.distorted.library.type.DynamicQuat;
47
import org.distorted.library.type.Static1D;
48
import org.distorted.library.type.Static3D;
49
import org.distorted.library.type.Static4D;
50

    
51
import java.io.DataInputStream;
52
import java.io.IOException;
53
import java.io.InputStream;
54

    
55
import javax.microedition.khronos.egl.EGLConfig;
56
import javax.microedition.khronos.opengles.GL10;
57

    
58
import static org.distorted.examples.meshfile.MeshFileActivity.PROCEDURAL;
59

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

    
62
class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
63
{
64
    private final float DEFAULT_SCALE = 0.3f;
65

    
66
    private GLSurfaceView mView;
67
    private DistortedTexture mTexture;
68
    private DistortedScreen mScreen;
69
    private DistortedEffects mEffects;
70
    private Static3D mScale;
71
    private long mTime;
72
    private float mCurrentScale;
73
    private MeshBase mMesh;
74

    
75
    Static4D mQuat1, mQuat2;
76
    int mScreenMin;
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

    
80
    MeshFileRenderer(GLSurfaceView v)
81
      {
82
      mView = v;
83
      mScreen = new DistortedScreen();
84
      mScale= new Static3D(1,1,1);
85
      Static3D center=new Static3D(0,0,0);
86

    
87
      mCurrentScale = DEFAULT_SCALE;
88

    
89
      mQuat1 = new Static4D(0,0,0,1);
90
      mQuat2 = new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
91

    
92
      DynamicQuat quatInt1 = new DynamicQuat(0,0.5f);
93
      DynamicQuat quatInt2 = new DynamicQuat(0,0.5f);
94

    
95
      quatInt1.add(mQuat1);
96
      quatInt2.add(mQuat2);
97

    
98
      VertexEffectDisappear disappear = new VertexEffectDisappear();
99
      disappear.setMeshAssociation(1,-1);
100

    
101
      mEffects = new DistortedEffects();
102
      mEffects.apply( new MatrixEffectQuaternion(quatInt2, center) );
103
      mEffects.apply( new MatrixEffectQuaternion(quatInt1, center) );
104
      mEffects.apply( new MatrixEffectScale(mScale));
105

    
106
      mEffects.apply( disappear );
107

    
108
      mScreen.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
109
      mScreen.showFPS();
110
      }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
   
114
    public void onDrawFrame(GL10 glUnused) 
115
      {
116
      mScreen.render( System.currentTimeMillis() );
117
      }
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120
    
121
    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
122
      {
123
      mScreenMin = Math.min(width, height);
124
      float factor = mCurrentScale*mScreenMin;
125
      mScale.set(factor,factor,factor);
126
      mScreen.resize(width, height);
127
      }
128

    
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130
    
131
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
132
      {
133
      if( mTexture==null ) mTexture = new DistortedTexture();
134

    
135
      VertexEffectDisappear.enable();
136

    
137
      VertexEffectRotate.enable();
138
      VertexEffectDeform.enable();
139

    
140
      DistortedLibrary.setMax(EffectType.VERTEX, 12);
141

    
142
      DistortedLibrary.onCreate(mView.getContext(), this);
143
      }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
    public void distortedException(Exception ex)
148
      {
149
      android.util.Log.e("MeshFile", ex.getMessage() );
150
      }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153
//   0 ---> 0
154
//  50 ---> DEFAULT_SCALE
155
// 100 ---> 4*DEFAULT_SCALE
156

    
157
    void setScale(int scale)
158
      {
159
      if( scale<= 50 )
160
        {
161
        mCurrentScale = DEFAULT_SCALE * scale / 50.0f;
162
        }
163
      else
164
        {
165
        mCurrentScale = DEFAULT_SCALE * ( 3*(scale/50.0f) - 2.0f);
166
        }
167

    
168
      float factor = mCurrentScale*mScreenMin;
169
      mScale.set(factor,factor,factor);
170
      }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
    void open(int resourceID)
175
      {
176
      if( mTexture==null ) mTexture = new DistortedTexture();
177
      mTexture.setTexture( createTexture(resourceID) );
178

    
179
      long t1 = System.currentTimeMillis();
180

    
181
      if( resourceID!=PROCEDURAL )
182
        {
183
        openMesh(resourceID);
184
        }
185
      else
186
        {
187
        createMesh();
188
        }
189

    
190
      long t2 = System.currentTimeMillis();
191

    
192
      mTime = t2-t1;
193

    
194
      mScreen.detachAll();
195
      mScreen.attach(mTexture,mEffects,mMesh);
196
      }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

    
200
    private Bitmap createTexture(int resourceID)
201
      {
202
      switch(resourceID)
203
          {
204
          case  R.raw.deferredjob:
205
          case  R.raw.meshjoin   : final int[] TET_COLORS4 = new int[] { 0xffffff00,
206
                                                                         0xff00ff00,
207
                                                                         0xff0000ff,
208
                                                                         0xffff0000 };
209
                                   return createTetrahedronTexture(TET_COLORS4);
210
          case  R.raw.predeform  : return createGridTexture(3);
211
          case  R.raw.cube2      :
212
          case  R.raw.cube3      :
213
          case  R.raw.cube4      :
214
          case  R.raw.cube5      : final int[] CUBE_COLORS = new int[] { 0xffffff00,
215
                                                                         0xffffffff,
216
                                                                         0xff0000ff,
217
                                                                         0xff00ff00,
218
                                                                         0xffff0000,
219
                                                                         0xffb5651d };
220
                                   return createCubeTexture(CUBE_COLORS);
221
          case  PROCEDURAL       :
222
          case  R.raw.pyra3      :
223
          case  R.raw.pyra4      :
224
          case  R.raw.pyra5      : final int[] TET_COLORS5 = new int[] { 0xffffff00,
225
                                                                         0xff00ff00,
226
                                                                         0xff0000ff,
227
                                                                         0xffff0000,
228
                                                                         0xff000000 };
229
                                   return createTetrahedronTexture(TET_COLORS5);
230
          case  R.raw.dino       : final int[] TET_COLORS7 = new int[] { 0xffffff00,
231
                                                                         0xffffffff,
232
                                                                         0xff0000ff,
233
                                                                         0xff00ff00,
234
                                                                         0xffff0000,
235
                                                                         0xffb5651d,
236
                                                                         0xff000000 };
237
                                   return createTetrahedronTexture(TET_COLORS7);
238
          }
239

    
240
      return null;
241
      }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
    private Bitmap createCubeTexture(int[] faceColors)
246
      {
247
      final int FACES=faceColors.length;
248
      int SIZE = 200;
249
      final float R = SIZE*0.10f;
250
      final float M = SIZE*0.05f;
251

    
252
      Bitmap bitmap;
253
      Paint paint = new Paint();
254
      bitmap = Bitmap.createBitmap( (FACES+1)*SIZE, SIZE, Bitmap.Config.ARGB_8888);
255
      Canvas canvas = new Canvas(bitmap);
256

    
257
      paint.setStyle(Paint.Style.FILL);
258
      paint.setColor(0xff000000);
259
      canvas.drawRect(0, 0, (FACES+1)*SIZE, SIZE, paint);
260

    
261
      for(int face=0; face<FACES; face++)
262
        {
263
        paint.setColor(faceColors[face]);
264
        canvas.drawRoundRect( face*SIZE+M, M, (face+1)*SIZE-M, SIZE-M, R, R, paint);
265
        }
266

    
267
      return bitmap;
268
      }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
    private Bitmap createGridTexture(int lines)
273
      {
274
      int SIZE = 200;
275
      Bitmap bitmap = Bitmap.createBitmap(SIZE,SIZE, Bitmap.Config.ARGB_8888);
276
      Canvas canvas = new Canvas(bitmap);
277

    
278
      Paint paint = new Paint();
279
      paint.setColor(0xff008800);
280
      paint.setStyle(Paint.Style.FILL);
281
      canvas.drawRect(0, 0, SIZE, SIZE, paint);
282
      paint.setColor(0xffffffff);
283

    
284
      for(int i=0; i<=lines ; i++ )
285
        {
286
        int x = (SIZE*i)/lines;
287
        canvas.drawRect(x-1,   0,  x+1, SIZE, paint);
288
        canvas.drawRect(  0, x-1, SIZE,  x+1, paint);
289
        }
290

    
291
      return bitmap;
292
      }
293

    
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295

    
296
    private Bitmap createTetrahedronTexture(int[] faceColors)
297
      {
298
      final float SQ3 = (float)Math.sqrt(3);
299
      final int FACES=faceColors.length;
300
      int SIZE = 256;
301
      float STROKE = 0.05f*SIZE;
302
      float OFF = STROKE/2 -1;
303
      float OFF2 = 0.5f*SIZE + OFF;
304
      float HEIGHT = SIZE - OFF;
305
      float RADIUS = SIZE/12.0f;
306
      float ARC1_H = 0.2f*SIZE;
307
      float ARC1_W = SIZE*0.5f;
308
      float ARC2_W = 0.153f*SIZE;
309
      float ARC2_H = 0.905f*SIZE;
310
      float ARC3_W = SIZE-ARC2_W;
311

    
312
      float M = SQ3/2;
313
      float D = (M/2 - 0.51f)*SIZE;
314

    
315
      Bitmap result = Bitmap.createBitmap(FACES*SIZE,SIZE, Bitmap.Config.ARGB_8888);
316
      Canvas canvas = new Canvas(result);
317
      Paint paint = new Paint();
318
      paint.setAntiAlias(true);
319
      paint.setStrokeWidth(STROKE);
320

    
321
      for(int i=0; i<FACES; i++)
322
        {
323
        paint.setColor(faceColors[i]);
324
        paint.setStyle(Paint.Style.FILL);
325

    
326
        canvas.drawRect(i*SIZE,0,(i+1)*SIZE,SIZE,paint);
327

    
328
        paint.setColor(0xff000000);
329
        paint.setStyle(Paint.Style.STROKE);
330

    
331
        canvas.drawLine(           i*SIZE, M*HEIGHT+D,  SIZE       +i*SIZE, M*HEIGHT+D, paint);
332
        canvas.drawLine(      OFF +i*SIZE, M*SIZE  +D,       OFF2  +i*SIZE,          D, paint);
333
        canvas.drawLine((SIZE-OFF)+i*SIZE, M*SIZE  +D, (SIZE-OFF2) +i*SIZE,          D, paint);
334

    
335
        canvas.drawArc( ARC1_W-RADIUS+i*SIZE, M*(ARC1_H-RADIUS)+D, ARC1_W+RADIUS+i*SIZE, M*(ARC1_H+RADIUS)+D, 225, 90, false, paint);
336
        canvas.drawArc( ARC2_W-RADIUS+i*SIZE, M*(ARC2_H-RADIUS)+D, ARC2_W+RADIUS+i*SIZE, M*(ARC2_H+RADIUS)+D, 105, 90, false, paint);
337
        canvas.drawArc( ARC3_W-RADIUS+i*SIZE, M*(ARC2_H-RADIUS)+D, ARC3_W+RADIUS+i*SIZE, M*(ARC2_H+RADIUS)+D, 345, 90, false, paint);
338
        }
339

    
340
      return result;
341
      }
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  private MeshBase createStaticMesh()
345
    {
346
    final float SQ2 = (float)Math.sqrt(2);
347
    final float SQ3 = (float)Math.sqrt(3);
348
    final float angleFaces = (float)((180/Math.PI)*(2*Math.asin(SQ3/3))); // angle between two faces of a tetrahedron
349
    final int MESHES=4;
350

    
351
    int association = 1;
352
    MeshBase[] meshes;
353

    
354
    float D = 0.0005f;
355
    float E = SQ3/2 - 3*D*SQ2;
356
    float F = 0.5f - D*SQ2*SQ3;
357

    
358
    float[] vertices = { -F,-E/3, +F,-E/3, 0.0f,2*E/3};
359
    float[] bands = new float[] {    1.0f    ,-D,
360
                                     1.0f  -D,-D*0.80f,
361
                                     1.0f-2*D,-D*0.65f,
362
                                     1.0f-4*D,+D*0.10f,
363
                                     0.50f, 0.035f,
364
                                     0.0f, 0.040f };
365

    
366
    meshes = new MeshPolygon[MESHES];
367
    meshes[0] = new MeshPolygon(vertices, bands, 2,2);
368
    meshes[0].setEffectAssociation(0,association,0);
369

    
370
    for(int i=1; i<MESHES; i++)
371
      {
372
      association <<= 1;
373
      meshes[i] = meshes[0].copy(true);
374
      meshes[i].setEffectAssociation(0,association,0);
375
      }
376

    
377
    MeshBase result = new MeshJoined(meshes);
378

    
379
    Static3D a0 = new Static3D(         0,        1,       0 );
380
    Static3D a1 = new Static3D(         0,  -1.0f/3, 2*SQ2/3 );
381
    Static3D a2 = new Static3D(-SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
382
    Static3D a3 = new Static3D( SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
383

    
384
    float tetraHeight = SQ2*SQ3/3;
385
    float d1 = (0.75f-2*SQ2*D)*tetraHeight;
386
    float d2 =-0.06f*tetraHeight;
387
    float d3 = 0.05f*tetraHeight;
388
    float d4 = 0.70f*tetraHeight;
389
    float d5 = 1.2f;
390

    
391
    Static3D dCen0 = new Static3D( d1*a0.get0(), d1*a0.get1(), d1*a0.get2() );
392
    Static3D dCen1 = new Static3D( d1*a1.get0(), d1*a1.get1(), d1*a1.get2() );
393
    Static3D dCen2 = new Static3D( d1*a2.get0(), d1*a2.get1(), d1*a2.get2() );
394
    Static3D dCen3 = new Static3D( d1*a3.get0(), d1*a3.get1(), d1*a3.get2() );
395

    
396
    Static3D dVec0 = new Static3D( d2*a0.get0(), d2*a0.get1(), d2*a0.get2() );
397
    Static3D dVec1 = new Static3D( d2*a1.get0(), d2*a1.get1(), d2*a1.get2() );
398
    Static3D dVec2 = new Static3D( d2*a2.get0(), d2*a2.get1(), d2*a2.get2() );
399
    Static3D dVec3 = new Static3D( d2*a3.get0(), d2*a3.get1(), d2*a3.get2() );
400

    
401
    Static4D dReg  = new Static4D(0,0,0,d3);
402
    Static1D dRad  = new Static1D(1);
403
    Static3D center= new Static3D(0,0,0);
404
    Static4D sReg  = new Static4D(0,0,0,d4);
405
    Static1D sink  = new Static1D(d5);
406

    
407
    Static1D angle  = new Static1D(angleFaces);
408
    Static3D axis1  = new Static3D(  -1, 0,      0);
409
    Static3D axis2  = new Static3D(0.5f, 0, -SQ3/2);
410
    Static3D axis3  = new Static3D(0.5f, 0, +SQ3/2);
411
    Static3D center1= new Static3D(0,-SQ3*SQ2/12,-SQ3/6);
412
    Static3D center2= new Static3D(0,-SQ3*SQ2/12,+SQ3/3);
413

    
414
    VertexEffectRotate  effect1 = new VertexEffectRotate( new Static1D(90), new Static3D(1,0,0), center );
415
    VertexEffectMove    effect2 = new VertexEffectMove  ( new Static3D(0,-SQ3*SQ2/12,0) );
416
    VertexEffectRotate  effect3 = new VertexEffectRotate( new Static1D(180), new Static3D(0,0,1), center1 );
417
    VertexEffectRotate  effect4 = new VertexEffectRotate( angle, axis1, center1 );
418
    VertexEffectRotate  effect5 = new VertexEffectRotate( angle, axis2, center2 );
419
    VertexEffectRotate  effect6 = new VertexEffectRotate( angle, axis3, center2 );
420

    
421
    VertexEffectDeform  effect7 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
422
    VertexEffectDeform  effect8 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
423
    VertexEffectDeform  effect9 = new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
424
    VertexEffectDeform  effect10= new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
425

    
426
    VertexEffectSink    effect11= new VertexEffectSink(sink,center, sReg);
427

    
428
    effect3.setMeshAssociation(14,-1);  // apply to mesh[1], [2] and [3]
429
    effect4.setMeshAssociation( 2,-1);  // apply only to mesh[1]
430
    effect5.setMeshAssociation( 4,-1);  // apply only to mesh[2]
431
    effect6.setMeshAssociation( 8,-1);  // apply only to mesh[3]
432

    
433
    result.apply(effect1);
434
    result.apply(effect2);
435
    result.apply(effect3);
436
    result.apply(effect4);
437
    result.apply(effect5);
438
    result.apply(effect6);
439

    
440
    result.apply(effect7);
441
    result.apply(effect8);
442
    result.apply(effect9);
443
    result.apply(effect10);
444

    
445
    result.apply(effect11);
446

    
447
    final float ratio = 0.2f;
448
    final Static4D[] maps = new Static4D[MESHES];
449

    
450
    for(int mesh=0; mesh<MESHES; mesh++)
451
      {
452
      maps[mesh] = new Static4D( mesh*ratio, 0.0f, ratio, 1.0f);
453
      }
454

    
455
    result.setTextureMap(maps,0);
456
    result.setShowNormals(true);
457

    
458
    return result;
459
    }
460

    
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462

    
463
    private void createMesh()
464
      {
465
      mMesh = createStaticMesh();
466

    
467
      int numEff = mMesh.numEffComponents();
468

    
469
      for(int i=0; i<numEff; i++)
470
        {
471
        mMesh.setEffectAssociation(i, 0, i);
472
        }
473
      }
474

    
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476

    
477
    private void openMesh(int resourceID)
478
      {
479
      Context con = mView.getContext();
480
      Resources res = con.getResources();
481
      InputStream is = res.openRawResource(resourceID);
482
      DataInputStream dos = new DataInputStream(is);
483
      mMesh = new MeshFile(dos);
484

    
485
      int numEff = mMesh.numEffComponents();
486

    
487
      for(int i=0; i<numEff; i++)
488
        {
489
        mMesh.setEffectAssociation(i, 0, i);
490
        }
491

    
492
      try
493
        {
494
        is.close();
495
        }
496
      catch(IOException e)
497
        {
498
        android.util.Log.e("MeshFile", "Error closing InputStream: "+e.toString());
499
        }
500
      }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

    
504
    MeshBase getMesh()
505
      {
506
      return mMesh;
507
      }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
    long getTime()
512
      {
513
      return mTime;
514
      }
515

    
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
    int getBytes()
519
      {
520
      if( mMesh instanceof MeshFile )
521
        {
522
        return ((MeshFile)mMesh).getNumBytes();
523
        }
524

    
525
      return 0;
526
      }
527

    
528
///////////////////////////////////////////////////////////////////////////////////////////////////
529

    
530
    int getVertices()
531
      {
532
      return mMesh.getNumVertices();
533
      }
534

    
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536

    
537
    int getEndEffIndex(int component)
538
      {
539
      return mMesh.getLastVertexEff(component);
540
      }
541

    
542
///////////////////////////////////////////////////////////////////////////////////////////////////
543

    
544
    int getEndTexIndex(int component)
545
      {
546
      return mMesh.getLastVertexTex(component);
547
      }
548

    
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550

    
551
    int getEffComponentNum()
552
      {
553
      return mMesh.numEffComponents();
554
      }
555

    
556
///////////////////////////////////////////////////////////////////////////////////////////////////
557

    
558
    int getTexComponentNum()
559
      {
560
      return mMesh.numTexComponents();
561
      }
562
}
(2-2/3)