Project

General

Profile

« Previous | Next » 

Revision 6a06a912

Added by Leszek Koltunski almost 8 years ago

  • ID 6a06a9124c05ef780773a82aa4511750e95fb70d
  • Child 5da25649

Initial commit

View differences:

build.gradle
1
apply plugin: 'com.android.library'
2

  
3
android {
4
    compileSdkVersion 22
5
    buildToolsVersion "23.0.3"
6

  
7
    defaultConfig {
8
        minSdkVersion 15
9
        targetSdkVersion 23
10
    }
11

  
12
    buildTypes {
13
        release {
14
            minifyEnabled false
15
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
16
        }
17
    }
18
}
src/main/AndroidManifest.xml
1
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
    package="org.distorted.library"
3
    android:versionCode="1"
4
    android:versionName="1.0" >
5

  
6
    <uses-sdk
7
        android:minSdkVersion="10"
8
        android:targetSdkVersion="19" />
9

  
10
</manifest>
src/main/java/org/distorted/library/Distorted.java
1
package org.distorted.library;
2

  
3
import java.io.BufferedReader;
4
import java.io.IOException;
5
import java.io.InputStream;
6
import java.io.InputStreamReader;
7

  
8
import android.opengl.GLSurfaceView;
9
import android.opengl.GLES20;
10
import android.os.Build;
11
import android.util.Log;
12

  
13
import org.distorted.library.R;
14
import org.distorted.library.exception.*;
15

  
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17
/**
18
 * A singleton class used to control various global settings.
19
 */
20
public class Distorted 
21
{
22
  /**
23
   * When creating an instance of a DistortedBitmap from another instance, do not clone anything.
24
   * Used in the copy constructor.
25
   */
26
  public static final int CLONE_NOTHING = 0x0;
27
  /**
28
   * When creating an instance of a DistortedObject from another instance, clone the Bitmap that's
29
   * backing up our DistortedObject. 
30
   * <p>
31
   * This way we can have two DistortedObjects, both backed up by the same Bitmap, to which we can 
32
   * apply different effects. Used in the copy constructor.
33
   */
34
  public static final int CLONE_BITMAP  = 0x1;
35
  /**
36
   * When creating an instance of a DistortedObject from another instance, clone the Matrix Effects.
37
   * <p>
38
   * This way we can have two different DistortedObjects with different Bitmaps behind them, both 
39
   * always displayed in exactly the same place on the screen. Applying any matrix-based effect to 
40
   * one of them automatically applies the effect to the other. Used in the copy constructor.
41
   */
42
  public static final int CLONE_MATRIX  = 0x2;
43
  /**
44
   * When creating an instance of a DistortedObject from another instance, clone the Vertex Effects.
45
   * <p>
46
   * This way we can have two different DistortedObjects with different Bitmaps behind them, both 
47
   * always with the same Vertex effects. Applying any vertex-based effect to one of them automatically 
48
   * applies the effect to the other. Used in the copy constructor.
49
   */
50
  public static final int CLONE_VERTEX  = 0x4;
51
  /**
52
   * When creating an instance of a DistortedObject from another instance, clone the Fragment Effects.
53
   * <p>
54
   * This way we can have two different DistortedObjects with different Bitmaps behind them, both 
55
   * always with the same Fragment effects. Applying any fragment-based effect to one of them automatically 
56
   * applies the effect to the other. Used in the copy constructor.
57
   */
58
  public static final int CLONE_FRAGMENT= 0x8;
59
  /**
60
   * When creating an instance of a DistortedNode from another instance, clone the children Nodes.
61
   * <p>
62
   * This is mainly useful for creating many similar sub-trees of Bitmaps and rendering then at different places
63
   * on the screen, with (optionally) different effects of the top-level root Bitmap.   
64
   */
65
  public static final int CLONE_CHILDREN= 0x10;
66
  /**
67
  * Constant used to represent a Matrix-based effect.
68
  */
69
  public static final int TYPE_MATR = 0x1;
70
  /**
71
   * Constant used to represent a Vertex-based effect.
72
   */
73
  public static final int TYPE_VERT = 0x2;
74
  /**
75
   * Constant used to represent a Fragment-based effect.
76
   */
77
  public static final int TYPE_FRAG = 0x4;
78
   
79
  private static final String TAG = Distorted.class.getSimpleName();
80
  private static boolean mInitialized = false;
81
  
82
  static int mPositionH;      // pass in model position information
83
  static int mColorH;         // pass in model color information
84
  static int mTextureUniformH;// pass in the texture.
85
  static int mNormalH;        // pass in model normal information.
86
  static int mTextureCoordH;  // pass in model texture coordinate information.
87
  static int mProgramH;       // This is a handle to our shading program.  
88

  
89
  static DistortedProjection mProjection = new DistortedProjection(false);
90
  static float mFOV = 60.0f;
91
  
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

  
94
  private Distorted()
95
    {
96
    
97
    }
98

  
99
///////////////////////////////////////////////////////////////////////////////////////////////////
100
  
101
  private static void sanitizeMaxValues() throws VertexUniformsException,FragmentUniformsException
102
    {
103
    int maxV,maxF;  
104
    int[] param = new int[1];
105
    
106
    GLES20.glGetIntegerv(GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, param, 0);
107
    maxV = param[0];
108
    GLES20.glGetIntegerv(GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, param, 0);
109
    maxF = param[0];
110
    
111
    Log.d(TAG, "Max vectors in vertex shader: "+maxV);
112
    Log.d(TAG, "Max vectors in fragment shader: "+maxF);
113
    
114
    if( Build.FINGERPRINT.startsWith("generic") == false )
115
      {
116
      int realMaxV = (maxV-11)/4;   // adjust this in case of changes to the shaders...
117
      int realMaxF = (maxF- 2)/4;   //
118
    
119
      if( EffectListVertex.getMax() > realMaxV )
120
        {
121
        throw new VertexUniformsException("Too many effects in the vertex shader, max is "+realMaxV, realMaxV);
122
        }
123
      if( EffectListFragment.getMax() > realMaxF )
124
        {
125
        throw new FragmentUniformsException("Too many effects in the fragment shader, max is "+realMaxF, realMaxF);
126
        }
127
      }
128
    }
129
  
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

  
132
  private static int compileShader(final int shaderType, final String shaderSource) throws FragmentCompilationException,VertexCompilationException
133
    {
134
    int shaderHandle = GLES20.glCreateShader(shaderType);
135

  
136
    if (shaderHandle != 0) 
137
      {
138
      GLES20.glShaderSource(shaderHandle, "#version 100 \n"+ generateShaderHeader(shaderType) + shaderSource);
139
      GLES20.glCompileShader(shaderHandle);
140
      final int[] compileStatus = new int[1];
141
      GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
142

  
143
      if (compileStatus[0] != GLES20.GL_TRUE ) 
144
        {
145
        GLES20.glDeleteShader(shaderHandle);
146
        shaderHandle = 0;
147
        }
148
      }
149

  
150
    if (shaderHandle == 0)
151
      {     
152
      String error = GLES20.glGetShaderInfoLog(shaderHandle);
153
     
154
      switch(shaderType)
155
        {
156
        case GLES20.GL_VERTEX_SHADER  : throw new VertexCompilationException(error); 
157
        case GLES20.GL_FRAGMENT_SHADER: throw new FragmentCompilationException(error);
158
        default                       : throw new RuntimeException(error);
159
        }
160
      }
161

  
162
    return shaderHandle;
163
    }
164

  
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166

  
167
  private static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) throws LinkingException
168
    {
169
    int programHandle = GLES20.glCreateProgram();
170

  
171
    if (programHandle != 0) 
172
      {
173
      GLES20.glAttachShader(programHandle, vertexShaderHandle);         
174
      GLES20.glAttachShader(programHandle, fragmentShaderHandle);
175

  
176
      if (attributes != null)
177
        {
178
        final int size = attributes.length;
179

  
180
        for (int i = 0; i < size; i++)
181
          {
182
          GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
183
          }                
184
        }
185

  
186
      GLES20.glLinkProgram(programHandle);
187

  
188
      final int[] linkStatus = new int[1];
189
      GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
190

  
191
      if (linkStatus[0] != GLES20.GL_TRUE ) 
192
        {         
193
        String error = GLES20.glGetProgramInfoLog(programHandle);
194
        GLES20.glDeleteProgram(programHandle);
195
        throw new LinkingException(error);
196
        }
197
      
198
      final int[] numberOfUniforms = new int[1];
199
      GLES20.glGetProgramiv(programHandle, GLES20.GL_ACTIVE_UNIFORMS, numberOfUniforms, 0);
200

  
201
      android.util.Log.d(TAG, "number of active uniforms="+numberOfUniforms[0]);
202
      }
203
 
204
    return programHandle;
205
    }
206
 
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208
  
209
  private static String generateShaderHeader(final int type)
210
    {
211
    String header="";
212
   
213
    switch(type)
214
      {
215
      case GLES20.GL_VERTEX_SHADER  : header += ("#define NUM_VERTEX "  +EffectListVertex.getMax()+"\n");
216
     
217
                                      for(EffectNames name: EffectNames.values() )
218
                                        {
219
                                        if( name.getType()==TYPE_VERT )  
220
                                        header += ("#define "+name.name()+" "+name.ordinal()+"\n");  
221
                                        }
222
                                      break;
223
      case GLES20.GL_FRAGMENT_SHADER: header += ("#define NUM_FRAGMENT "+EffectListFragment.getMax()+"\n");
224
     
225
                                      for(EffectNames name: EffectNames.values() )
226
                                        {
227
                                        if( name.getType()==TYPE_FRAG )  
228
                                        header += ("#define "+name.name()+" "+name.ordinal()+"\n");  
229
                                        }
230
                                      break;
231
     }
232
   
233
    //Log.d(TAG,""+header);
234
    
235
    return header;
236
    }
237
  
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239
  
240
  private static String readTextFileFromRawResource(final GLSurfaceView v, final int resourceId)
241
    {
242
    final InputStream inputStream = v.getContext().getResources().openRawResource(resourceId);
243
    final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
244
    final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
245
 
246
    String nextLine;
247
    final StringBuilder body = new StringBuilder();
248
 
249
    try
250
      {
251
      while ((nextLine = bufferedReader.readLine()) != null)
252
        {
253
        body.append(nextLine);
254
        body.append('\n');
255
        }
256
      }
257
    catch (IOException e)
258
      {
259
      return null;
260
      }
261
 
262
    return body.toString();
263
    }
264
 
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266
 
267
  private static String getVertexShader(final GLSurfaceView v)
268
    {
269
    return readTextFileFromRawResource( v, R.raw.main_vertex_shader);
270
    }
271
 
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273
 
274
  private static String getFragmentShader(final GLSurfaceView v)
275
    {
276
    return readTextFileFromRawResource( v, R.raw.main_fragment_shader);
277
    }
278

  
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280
// Public API
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282
/**
283
 * Sets Vertical Field of View angle. This changes the Projection Matrix.  
284
 *   
285
 * @param fov Vertical Field Of View angle, in degrees. If T is the middle of the top edge of the 
286
 *            screen, E is the eye point, and B is the middle of the bottom edge of the screen, then 
287
 *            fov = angle(TEB)
288
 */
289
  public static void setFov(float fov)
290
    {
291
    mFOV = fov;
292
   
293
    if( mProjection.width>0 && mProjection.height>0 )
294
      mProjection.onSurfaceChanged( (int)mProjection.width, (int)mProjection.height);
295
    }
296
  
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298
/**
299
 * When OpenGL context gets created, you need to call this method so that the library can initialise its internal data structures.
300
 * I.e. best called from GLSurfaceView.onSurfaceCreated().
301
 * <p>
302
 * Compiles the vertex and fragment shaders, establishes the addresses of all uniforms, and initialises all Bitmaps that have already
303
 * been created.
304
 *   
305
 * @param v The Surface that just got created.
306
 * @throws FragmentCompilationException
307
 * @throws VertexCompilationException
308
 * @throws VertexUniformsException
309
 * @throws FragmentUniformsException
310
 * @throws LinkingException
311
 */
312
  public static void onSurfaceCreated(GLSurfaceView v) throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
313
    { 
314
    mInitialized = true;  
315
     
316
// String ver;  
317
    
318
    final String vertexShader   = Distorted.getVertexShader(v);         
319
    final String fragmentShader = Distorted.getFragmentShader(v);       
320
/*
321
    ver = GLES20.glGetString(GLES20.GL_SHADING_LANGUAGE_VERSION);    
322
    Log.d(TAG, "GLSL version: "+(ver==null ? "null" : ver) );
323
    ver = GLES20.glGetString(GLES20.GL_VERSION);   
324
    Log.d(TAG, "GL version: "+(ver==null ? "null" : ver) );
325
    ver = GLES20.glGetString(GLES20.GL_VENDOR);    
326
    Log.d(TAG, "GL vendor: "+(ver==null ? "null" : ver) );
327
    ver = GLES20.glGetString(GLES20.GL_RENDERER);  
328
    Log.d(TAG, "GL renderer: "+(ver==null ? "null" : ver) );
329
*/
330
    //ver = GLES20.glGetString(GLES20.GL_EXTENSIONS);    
331
    //Log.d(TAG, "GL extensions: "+(ver==null ? "null" : ver) );
332
    
333
    sanitizeMaxValues();
334
    
335
    final int vertexShaderHandle   = compileShader(GLES20.GL_VERTEX_SHADER  , vertexShader  );     
336
    final int fragmentShaderHandle = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);     
337
      
338
    mProgramH = createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, new String[] {"a_Position",  "a_Color", "a_Normal", "a_TexCoordinate"});                                                            
339
      
340
    GLES20.glUseProgram(mProgramH);
341
    GLES20.glEnable (GLES20.GL_DEPTH_TEST);
342
    GLES20.glDepthFunc(GLES20.GL_LEQUAL);
343
    GLES20.glEnable(GLES20.GL_BLEND);
344
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
345
    
346
    mTextureUniformH = GLES20.glGetUniformLocation(mProgramH, "u_Texture");
347
    
348
    mPositionH       = GLES20.glGetAttribLocation( mProgramH, "a_Position");
349
    mColorH          = GLES20.glGetAttribLocation( mProgramH, "a_Color");
350
    mNormalH         = GLES20.glGetAttribLocation( mProgramH, "a_Normal"); 
351
    mTextureCoordH   = GLES20.glGetAttribLocation( mProgramH, "a_TexCoordinate");
352
    
353
    EffectListFragment.getUniforms(mProgramH);
354
    EffectListVertex.getUniforms(mProgramH);
355
    EffectListMatrix.getUniforms(mProgramH);
356
    
357
    GLES20.glEnableVertexAttribArray(mPositionH);        
358
    GLES20.glEnableVertexAttribArray(mColorH);
359
    GLES20.glEnableVertexAttribArray(mNormalH);
360
    GLES20.glEnableVertexAttribArray(mTextureCoordH);
361
   
362
    DistortedObjectList.reset();
363
    DistortedNode.reset();
364
    EffectMessageSender.startSending();
365
    }
366
  
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368
/**
369
 * Call this when the physical size of the surface we are rendering to changes.
370
 * I.e. must be called from GLSurfaceView.onSurfaceChanged()  
371
 *   
372
 * @param surfaceWidth  new width of the surface.
373
 * @param surfaceHeight new height of the surface.
374
 */
375
  public static void onSurfaceChanged(int surfaceWidth, int surfaceHeight)
376
    {
377
    mProjection.onSurfaceChanged(surfaceWidth, surfaceHeight);
378
    }
379

  
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381
/**
382
 * Call this so that the Library can release its internal data structures.
383
 * Must be called from Activity.onDestroy(). 
384
 */
385
  public static void onDestroy()
386
    {
387
    DistortedObjectList.release();
388
    
389
    EffectListVertex.reset();
390
    EffectListFragment.reset();
391
    EffectListMatrix.reset();
392
    EffectMessageSender.stopSending();
393
   
394
    mInitialized = false;
395
    }
396
  
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398
/**
399
 * Returns the true if onSurfaceCreated has been called already, and thus if the Library's is ready
400
 * to accept effect requests.
401
 * 
402
 * @return <code>true</code> if the Library is ready for action, <code>false</code> otherwise.
403
 */
404
  public static boolean isInitialized()
405
    {
406
    return mInitialized;  
407
    }
408

  
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410
/**
411
 * Returns the maximum number of Matrix effects.
412
 *    
413
 * @return The maximum number of Matrix effects
414
 */
415
  public static int getMaxMatrix()
416
    {
417
    return EffectListMatrix.getMax();  
418
    }
419
 
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421
/**
422
 * Returns the maximum number of Vertex effects.
423
 *    
424
 * @return The maximum number of Vertex effects
425
 */  
426
  public static int getMaxVertex()
427
    {
428
    return EffectListVertex.getMax();  
429
    }
430
  
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432
/**
433
 * Returns the maximum number of Fragment effects.
434
 *    
435
 * @return The maximum number of Fragment effects
436
 */  
437
  public static int getMaxFragment()
438
    {
439
    return EffectListFragment.getMax();  
440
    }
441
  
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443
/**
444
 * Sets the maximum number of Matrix effects that can be applied to a single DistortedBitmap at one time.
445
 * This can fail if the value of 'max' is outside permitted range. 
446
 * 
447
 * @param max new maximum number of simultaneous Matrix Effects. Has to be a non-negative number not greater
448
 *            than Byte.MAX_VALUE 
449
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
450
 */
451
  public static boolean setMaxMatrix(int max)
452
    {
453
    return EffectListMatrix.setMax(max);  
454
    }
455
  
456
///////////////////////////////////////////////////////////////////////////////////////////////////
457
/**
458
 * Sets the maximum number of Vertex effects that can be applied to a single DistortedBitmap at one time.
459
 * This can fail if:
460
 * <ul>
461
 * <li>the value of 'max' is outside permitted range
462
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called 
463
 *     before the Vertex Shader gets compiled, i.e. before the call to {@link #onSurfaceCreated}. After this
464
 *     time only decreasing the value of 'max' is permitted.  
465
 * </ul>
466
 * 
467
 * @param max new maximum number of simultaneous Vertex Effects. Has to be a non-negative number not greater
468
 *            than Byte.MAX_VALUE 
469
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
470
 */
471
  public static boolean setMaxVertex(int max)
472
    {
473
    return EffectListVertex.setMax(max);  
474
    }
475

  
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477
/**
478
 * Sets the maximum number of Fragment effects that can be applied to a single DistortedBitmap at one time.
479
 * This can fail if:
480
 * <ul>
481
 * <li>the value of 'max' is outside permitted range
482
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called 
483
 *     before the Fragment Shader gets compiled, i.e. before the call to {@link #onSurfaceCreated}. After this
484
 *     time only decreasing the value of 'max' is permitted.  
485
 * </ul>
486
 * 
487
 * @param max new maximum number of simultaneous Fragment Effects. Has to be a non-negative number not greater
488
 *            than Byte.MAX_VALUE 
489
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
490
 */
491
  public static boolean setMaxFragment(int max)
492
    {
493
    return EffectListFragment.setMax(max);  
494
    }
495
    
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497
//end of file  
498
}
src/main/java/org/distorted/library/DistortedBitmap.java
1
package org.distorted.library;
2

  
3
import android.graphics.Bitmap;
4

  
5
///////////////////////////////////////////////////////////////////////////////////////////////////
6
/**
7
 * Wrapper around the standard Android Bitmap class to which one can apply graphical effects.
8
 * <p>
9
 * General idea is as follows:
10
 * <ul>
11
 * <li> Create an instance of DistortedBitmap
12
 * <li> Paint something onto the Bitmap that's backing it up
13
 * <li> Apply some effects
14
 * <li> Draw it!
15
 * </ul>
16
 * <p>
17
 * The effects we can apply fall into three general categories:
18
 * <ul>
19
 * <li> Matrix Effects, i.e. ones that change the Bitmap's ModelView Matrix (moves, scales, rotations)
20
 * <li> Vertex Effects, i.e. effects that are implemented in the Vertex Shader. Those typically change
21
 *      the shape of (some sub-Region of) the Bitmap in some way (deforms, distortions, sinks)
22
 * <li> Fragment Effects, i.e. effects that change (some of) the pixels of the Bitmap (transparency, macroblock)
23
 * </ul>
24
 * <p>
25
 * 
26
 */
27
public class DistortedBitmap extends DistortedObject
28
   {
29
   
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31
// PUBLIC API
32
///////////////////////////////////////////////////////////////////////////////////////////////////  
33
/**
34
 * Default constructor: creates a DistortedBitmap (width,height) pixels in size, with the distortion
35
 * grid of size 'size' and does not fill it up with any Bitmap data just yet.
36
 * <p>
37
 * Distortion grid is a grid of rectangles the Bitmap is split to. The vertices of this grid are then 
38
 * moved around by the Vertex Shader to create various Vertex Effects.
39
 * <p>
40
 * Size parameter describes the horizontal size, i.e. the number of rectangles the top (or bottom) edge
41
 * is split to. So when size=1, the whole Bitmap is just one giant rectangle. When size=10, the Bitmap
42
 * is split into a grid of 10x10 rectangles.
43
 * <p>
44
 * The higher the size, the better Vertex Effects look; on the other hand too high size will slow things 
45
 * down.  
46
 *       
47
 * @param width  width of the DistortedBitmap, in pixels.
48
 * @param height height of the DistortedBitmap, in pixels.
49
 * @param size Horizontal size of the distortion grid. 2<=size&lt;256.
50
 */
51
   public DistortedBitmap(int width, int height, int gridSize)
52
     {     
53
     int xsize = gridSize;
54
     int ysize = xsize*height/width;
55
     
56
     if( xsize<2   ) xsize=  2;
57
     if( xsize>256 ) xsize=256;
58
     if( ysize<2   ) ysize=  2;
59
     if( ysize>256 ) ysize=256;
60
     
61
     mSizeX= width;
62
     mSizeY= height;
63
     mSizeZ= 1;     
64
     mGrid = new GridBitmap(xsize,ysize);
65
     initializeData(gridSize);
66
     }
67

  
68
///////////////////////////////////////////////////////////////////////////////////////////////////   
69
/**
70
 * Creates a DistortedBitmap and immediately fills it up with Bitmap data.
71
 * The dimensions of the created DistortedBitmap object are the same like that of the passed Bitmap.
72
 *       
73
 * @param bmp The android.graphics.Bitmap object to apply effects to and display.
74
 * @param size Horizontal size of the distortion grid. 1<=size&lt;256.
75
 */
76
   public DistortedBitmap(Bitmap bmp, int gridSize)
77
     {
78
     this(bmp.getWidth(), bmp.getHeight(), gridSize); 
79
     setBitmap(bmp);
80
     }
81
   
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83
/**
84
 * Copy constructor used to create a DistortedBitmap based on various parts of another Bitmap.
85
 * <p>
86
 * Whatever we do not clone gets created just like in the default constructor.
87
 *    
88
 * @param db    Source DistortedBitmap to create our object from
89
 * @param flags A bitmask of values specifying what to copy.
90
 *              For example, CLONE_BITMAP | CLONE_MATRIX.
91
 */
92
   public DistortedBitmap(DistortedBitmap db, int flags)
93
     {
94
     initializeEffectLists(db,flags);  
95
      
96
     mID = DistortedObjectList.add(this);
97
        
98
     mSizeX = db.mSizeX;
99
     mSizeY = db.mSizeY;
100
     mSizeZ = db.mSizeZ;
101
     mSize  = db.mSize;
102
     mGrid  = db.mGrid;
103
       
104
     if( (flags & Distorted.CLONE_BITMAP) != 0 ) 
105
       {
106
       mTextureDataH = db.mTextureDataH;
107
 	    mBmp          = db.mBmp;
108
 	    mBitmapSet    = db.mBitmapSet;
109
 	    }
110
     else
111
       {
112
       mTextureDataH   = new int[1];
113
       mTextureDataH[0]= 0;
114
       mBitmapSet      = new boolean[1];
115
       mBitmapSet[0]   = false;
116
       mBmp            = new Bitmap[1];
117
       mBmp[0]         = null;
118
       
119
       if( Distorted.isInitialized() ) resetTexture();
120
       }
121
     }
122

  
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124
}
125
    
src/main/java/org/distorted/library/DistortedCubes.java
1
package org.distorted.library;
2

  
3
import android.graphics.Bitmap;
4

  
5
///////////////////////////////////////////////////////////////////////////////////////////////////
6
/**
7
 * Instance of this class represents a connected, flat set of cubes optionally textured as a whole.
8
 * (a subset of a NxMx1 cuboid build with 1x1x1 cubes, i.e. the MxNx1 cuboid with arbitrary cubes missing)
9
 * <p>
10
 * General idea is as follows:
11
 * <ul>
12
 * <li> Create an instance of this class
13
 * <li> Optionally texture it
14
 * <li> Apply some effects
15
 * <li> Draw it!
16
 * </ul>
17
 * <p>
18
 * The effects we can apply fall into three general categories:
19
 * <ul>
20
 * <li> Matrix Effects, i.e. ones that change the Cuboid's ModelView Matrix (moves, scales, rotations)
21
 * <li> Vertex Effects, i.e. effects that are implemented in the Vertex Shader. Those typically change
22
 *      the shape of (some sub-Region of) the Cuboid in some way (deforms, distortions, sinks)
23
 * <li> Fragment Effects, i.e. effects that change (some of) the pixels of the Texture (transparency, macroblock)
24
 * </ul>
25
 * <p>
26
 * 
27
 */
28
public class DistortedCubes extends DistortedObject
29
   {
30
   
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32
// PUBLIC API
33
/////////////////////////////////////////////////////////////////////////////////////////////////// 
34
 
35
/**
36
 * Creates internal memory representation of a cuboid subset.
37
 * 
38
 * @param cols Integer helping to parse the next parameter.
39
 * @param desc String describing the subset of a MxNx1 cuboid that we want to create.
40
 *             Its MxN characters - all 0 or 1 - decide of appropriate field is taken or not.
41
 *             
42
 *             For example, (cols=2, desc="111010") describes the following shape:
43
 *             
44
 *             XX
45
 *             X
46
 *             X
47
 *             
48
 *             whereas (cols=2,desc="110001") describes
49
 *             
50
 *             XX
51
 *              
52
 *              X
53
 *              
54
 * @param gridSize size, in pixels, of the single 1x1x1 cube our cuboid is built from
55
 *  
56
 */   
57
   public DistortedCubes(int cols, String desc, int gridSize) 
58
     {
59
     this(cols,desc,gridSize,false);
60
     }
61

  
62
/**
63
 * @param frontOnly Only create the front wall or side and back as well?
64
 */
65
   
66
   public DistortedCubes(int cols, String desc, int gridSize, boolean frontOnly) 
67
     {
68
     int Rs = 0;
69
     int Cs = 0;
70
     
71
     if( cols>0 )
72
       {
73
       int reallen = desc.length();
74
       int len = reallen;
75

  
76
       if( (reallen/cols)*cols != reallen )
77
         {
78
         len = ((reallen/cols)+1)*cols; 
79
         for(int i=reallen; i<len; i++) desc += "0";
80
         }
81
    
82
       if( desc.indexOf("1")>=0 )
83
         {
84
         Cs = cols;
85
         Rs = len/cols;
86
         }
87
       }
88
     
89
     mSizeX= gridSize*Cs;
90
     mSizeY= gridSize*Rs;
91
     mSizeZ= frontOnly ? 0 : gridSize;
92
     mGrid = new GridCubes(cols,desc, frontOnly);
93
     initializeData(gridSize);
94
     }
95
   
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97
/**
98
 * Copy constructor used to create a DistortedCubes based on various parts of another object.
99
 * <p>
100
 * Whatever we do not clone gets created just like in the default constructor.
101
 *    
102
 * @param dc    Source object to create our object from
103
 * @param flags A bitmask of values specifying what to copy.
104
 *              For example, CLONE_BITMAP | CLONE_MATRIX.
105
 */
106
   public DistortedCubes(DistortedCubes dc, int flags)
107
     {
108
     initializeEffectLists(dc,flags);  
109
      
110
     mID = DistortedObjectList.add(this);
111
        
112
     mSizeX = dc.mSizeX;
113
     mSizeY = dc.mSizeY;
114
     mSizeZ = dc.mSizeZ;
115
     mSize  = dc.mSize;
116
     mGrid  = dc.mGrid;
117
       
118
     if( (flags & Distorted.CLONE_BITMAP) != 0 ) 
119
       {
120
       mTextureDataH = dc.mTextureDataH;
121
       mBmp          = dc.mBmp;
122
       mBitmapSet    = dc.mBitmapSet;
123
       }
124
     else
125
       {
126
       mTextureDataH   = new int[1];
127
       mTextureDataH[0]= 0;
128
       mBitmapSet      = new boolean[1];
129
       mBitmapSet[0]   = false;
130
       mBmp            = new Bitmap[1];
131
       mBmp[0]         = null;
132
       
133
       if( Distorted.isInitialized() ) resetTexture(); 
134
       }
135
     }
136

  
137
///////////////////////////////////////////////////////////////////////////////////////////////////   
138
   }
src/main/java/org/distorted/library/DistortedNode.java
1
package org.distorted.library;
2

  
3
import java.util.ArrayList;
4
import java.util.HashMap;
5

  
6
import android.opengl.GLES20;
7

  
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9
/**
10
 * Class which represents a Node in a Tree of DistortedBitmaps.
11
 *  
12
 * Having organized a set of DistortedBitmaps into a Tree, we can then render any Node to any Framebuffer.
13
 * That recursively renders the Bitmap held in the Node and all its children, along with whatever effects
14
 * each one of them has. 
15
 */
16
public class DistortedNode 
17
  {
18
  private static final int TEXTURE_FAILED_TO_CREATE = -1;   
19
  private static final int TEXTURE_NOT_CREATED_YET  = -2;   
20
   
21
  private DistortedBitmap mBitmap;
22
  private NodeData mData;
23
  
24
  private DistortedNode mParent;
25
  private ArrayList<DistortedNode> mChildren;
26
  private int[] mNumChildren;  // ==mChildren.length(), but we only create mChildren if the first one gets added
27
  
28
  private static HashMap<ArrayList<Long>,NodeData> mMapNodeID = new HashMap<ArrayList<Long>,NodeData>();
29
  private static long mNextNodeID =0;
30

  
31
  //////////////////////////////////////////////////////////////////
32
  
33
  private class NodeData
34
    {
35
    long ID;  
36
    int numPointingNodes;
37
    int mFramebufferID;
38
    int mTextureID;
39
    DistortedProjection mProjection;
40
    boolean mRendered;
41
    
42
  //////////////////////////////////////////////////////////////////
43
 
44
   public NodeData(long id)
45
     {
46
     ID = id;
47
     numPointingNodes= 1;
48
     mFramebufferID = 0;
49
     mTextureID = TEXTURE_NOT_CREATED_YET;
50
     mProjection = null;
51
     mRendered = false;
52
     }
53
   
54
  //////////////////////////////////////////////////////////////////
55

  
56
    boolean createFBO()
57
      {  
58
      int[] textureIds = new int[1];
59
      GLES20.glGenTextures(1, textureIds, 0);
60
      mTextureID = textureIds[0];
61
      int[] mFBORenderToTexture = new int[1];
62
      
63
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
64
      GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
65
      GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
66
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
67
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
68
      GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mProjection.width, mProjection.height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
69

  
70
      GLES20.glGenFramebuffers(1, mFBORenderToTexture, 0);
71
      GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBORenderToTexture[0]);
72
      GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mTextureID, 0);
73
      int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
74
    
75
      if(status != GLES20.GL_FRAMEBUFFER_COMPLETE)
76
        {
77
        android.util.Log.e("Node", "failed to create framebuffer, error="+status);  
78
        
79
        GLES20.glDeleteTextures(1, textureIds, 0);
80
        GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
81
        mFramebufferID = 0;
82
        mTextureID = TEXTURE_FAILED_TO_CREATE;
83
        return false;
84
        }
85
      
86
      mFramebufferID = mFBORenderToTexture[0];
87
      
88
      return true;
89
      }
90
   
91
  //////////////////////////////////////////////////////////////////
92

  
93
    void deleteFBO()
94
      {
95
      int[] textureIds = new int[1];
96
      int[] mFBORenderToTexture = new int[1];
97
     
98
      textureIds[0] = mTextureID;
99
      mFBORenderToTexture[0] = mFramebufferID;
100
      
101
      GLES20.glDeleteTextures(1, textureIds, 0);
102
      GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
103
      
104
      mFramebufferID = 0;
105
      mTextureID = TEXTURE_NOT_CREATED_YET;
106
      }
107
   }
108
 
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110

  
111
  private void markRecursive()
112
    {
113
    mData.mRendered = false;
114
   
115
    synchronized(this)
116
      {
117
      for(int i=0; i<mNumChildren[0]; i++) mChildren.get(i).markRecursive();
118
      }
119
    }
120
  
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
  
123
  private void drawRecursive(long currTime, DistortedProjection dp, int mFBO)
124
    {
125
    if( mNumChildren[0]<=0 )
126
      {
127
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBitmap.mTextureDataH[0]); 
128
      
129
      if( mData.mProjection!=null )
130
        {
131
        mData.deleteFBO();
132
        mData.mProjection = null;
133
        }
134
      }
135
    else
136
      {
137
      if( mData.mRendered==false )
138
        {
139
        mData.mRendered = true;
140
       
141
        if( mData.mTextureID==TEXTURE_NOT_CREATED_YET ) mData.createFBO();
142
       
143
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mData.mFramebufferID);
144
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
145
        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
146
      
147
        if( mBitmap.mBitmapSet[0] )
148
          {
149
          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBitmap.mTextureDataH[0]);        
150
          mBitmap.drawNoEffectsPriv(mData.mProjection);
151
          }
152
      
153
        synchronized(this)
154
          {
155
          for(int i=0; i<mNumChildren[0]; i++)
156
            {
157
            mChildren.get(i).drawRecursive(currTime, mData.mProjection, mData.mFramebufferID);
158
            }
159
          }
160
        }
161
      
162
      GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBO);
163
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mData.mTextureID);   // this is safe because we must have called createFBO() above before.     
164
      }
165
    
166
    mBitmap.drawPriv(currTime, dp);
167
    }
168
  
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170
// tree isomorphism
171
  
172
  private void RecomputeNodeID(ArrayList<Long> prev)
173
    {
174
    ArrayList<Long> curr = generateIDList();
175
     
176
    if( mParent==null )
177
      {
178
      adjustNodeData(prev,curr);
179
      }
180
    else
181
      {
182
      ArrayList<Long> parentPrev = mParent.generateIDList();
183
      adjustNodeData(prev,curr);
184
      mParent.RecomputeNodeID(parentPrev);
185
      }
186
    }
187

  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

  
190
  private ArrayList<Long> generateIDList()
191
    {
192
    ArrayList<Long> ret = new ArrayList<Long>();
193
     
194
    ret.add( mNumChildren[0]>0 ? mBitmap.getBitmapID() : mBitmap.getID() );
195
    DistortedNode node;
196
   
197
    for(int i=0; i<mNumChildren[0]; i++)
198
      {
199
      node = mChildren.get(i);
200
      ret.add(node.mData.ID);
201
      }
202
   
203
    return ret;
204
    }
205

  
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

  
208
  private void adjustNodeData(ArrayList<Long> oldList, ArrayList<Long> newList)
209
    {
210
    if( mData.numPointingNodes>1 ) mData.numPointingNodes--;
211
    else                           mMapNodeID.remove(oldList);  
212
   
213
    NodeData newData = mMapNodeID.get(newList);
214
    
215
    if( newData==null )
216
      {
217
      mData.ID = ++mNextNodeID;  
218
      mData.numPointingNodes = 1;
219
     
220
      if( newList.size()>1 && mData.mProjection==null )
221
        {     
222
        mData.mProjection = new DistortedProjection(true);
223
        mData.mProjection.onSurfaceChanged(mBitmap.getWidth(), mBitmap.getHeight());
224
        mData.mFramebufferID = 0;
225
        mData.mTextureID = TEXTURE_NOT_CREATED_YET;
226
        }
227
       
228
      mMapNodeID.put(newList, mData);
229
      }
230
    else
231
      {  
232
      newData.numPointingNodes++;
233
      mData = newData;
234
      }
235
    }
236

  
237
///////////////////////////////////////////////////////////////////////////////////////////////////  
238
// this will be called on startup and every time OpenGL context has been lost
239
// also call this from the constructor if the OpenGL context has been created already.
240
    
241
  static void reset()
242
    {
243
    NodeData tmp;   
244
     
245
    for(ArrayList<Long> key: mMapNodeID.keySet())
246
      {
247
      tmp = mMapNodeID.get(key);
248
          
249
      if( tmp.mProjection!=null )
250
        {
251
    	  tmp.mTextureID = TEXTURE_NOT_CREATED_YET;
252
        tmp.mRendered  = false;
253
        }
254
      }
255
    }
256
  
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
// PUBLIC API
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260
/**
261
 * Constructs new Node of the Tree.
262
 *     
263
 * @param bmp DistortedBitmap to put into the new Node.
264
 */
265
  public DistortedNode(DistortedBitmap bmp)
266
    {
267
    mBitmap = bmp;
268
    mParent = null;
269
    mChildren = null;
270
    mNumChildren = new int[1];
271
    mNumChildren[0] = 0;
272
   
273
    ArrayList<Long> list = new ArrayList<Long>();
274
    list.add(bmp.getID());
275
      
276
    mData = mMapNodeID.get(list);
277
   
278
    if( mData!=null )
279
      {
280
      mData.numPointingNodes++;
281
      }
282
    else
283
      {
284
      mData = new NodeData(++mNextNodeID);   
285
      mMapNodeID.put(list, mData);  
286
      }
287
    }
288

  
289
///////////////////////////////////////////////////////////////////////////////////////////////////  
290
/**
291
 * Copy-constructs new Node of the Tree from another Node.
292
 *     
293
 * @param node The DistortedNode to copy data from.
294
 * @param flags bit field composed of a subset of the following:
295
 *        {@link Distorted#CLONE_BITMAP},  {@link Distorted#CLONE_MATRIX}, {@link Distorted#CLONE_VERTEX},
296
 *        {@link Distorted#CLONE_FRAGMENT} and {@link Distorted#CLONE_CHILDREN}.
297
 *        For example flags = CLONE_BITMAP | CLONE_CHILDREN.
298
 */
299
  public DistortedNode(DistortedNode node, int flags)
300
    {
301
    mParent = null;  
302
    mBitmap = new DistortedBitmap(node.mBitmap, flags);  
303
   
304
    if( (flags & Distorted.CLONE_CHILDREN) != 0 ) 
305
      {
306
      mChildren = node.mChildren;
307
      mNumChildren = node.mNumChildren;
308
      }
309
    else
310
      {
311
      mChildren = null;
312
      mNumChildren = new int[1];
313
      mNumChildren[0] = 0;
314
      }
315
   
316
    ArrayList<Long> list = generateIDList();
317
   
318
    mData = mMapNodeID.get(list);
319
   
320
    if( mData!=null )
321
      {
322
      mData.numPointingNodes++;
323
      }
324
    else
325
      {
326
      mData = new NodeData(++mNextNodeID);   
327
      mMapNodeID.put(list, mData);
328
      }
329
    }
330
  
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332
/**
333
 * Adds a new child to the last position in the list of our Node's children.
334
 * 
335
 * @param node The new Node to add.
336
 * @return <code>true</code> if we successfully added the new child.
337
 */
338
  public synchronized void attach(DistortedNode node)
339
    {
340
    ArrayList<Long> prev = generateIDList(); 
341
   
342
    if( mChildren==null ) mChildren = new ArrayList<DistortedNode>(2);
343
     
344
    node.mParent = this;
345
    mChildren.add(node);
346
    mNumChildren[0]++;
347
     
348
    RecomputeNodeID(prev);
349
    }
350
   
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352
/**
353
 * Adds a new child to the last position in the list of our Node's children.
354
 * 
355
 * @param bmp DistortedBitmap to initialize our child Node with.
356
 * @return the newly constructed child Node, or null if we couldn't allocate resources.
357
 */
358
  public synchronized DistortedNode attach(DistortedBitmap bmp)
359
    {
360
    ArrayList<Long> prev = generateIDList(); 
361
      
362
    if( mChildren==null ) mChildren = new ArrayList<DistortedNode>(2);  
363
    DistortedNode node = new DistortedNode(bmp);
364
    node.mParent = this;
365
    mChildren.add(node);
366
    mNumChildren[0]++;
367
   
368
    RecomputeNodeID(prev);
369
   
370
    return node;
371
    }
372
  
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374
/**
375
 * Removes the first occurrence of a specified child from the list of children of our Node.
376
 * 
377
 * @param node The Node to remove.
378
 * @return <code>true</code> if the child was successfully removed.
379
 */
380
  public synchronized boolean detach(DistortedNode node)
381
    {
382
    if( mNumChildren[0]>0 )
383
      {
384
      ArrayList<Long> prev = generateIDList();  
385
         
386
      if( mChildren.remove(node) )
387
        {
388
        node.mParent = null;  
389
        mNumChildren[0]--;
390
     
391
        RecomputeNodeID(prev);
392
     
393
        return true;
394
        }
395
      }
396
   
397
    return false;
398
    }
399
  
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401
/**
402
 * Removes the first occurrence of a specified child from the list of children of our Node.
403
 * 
404
 * @param bmp The DistortedBitmap to remove.
405
 * @return <code>true</code> if the child was successfully removed.
406
 */
407
  public synchronized boolean detach(DistortedBitmap bmp)
408
    {
409
    long id = bmp.getID();
410
    DistortedNode node;
411
   
412
    for(int i=0; i<mNumChildren[0]; i++)
413
      {
414
      node = mChildren.get(i);
415
     
416
      if( node.mBitmap.getID()==id )
417
        {
418
        ArrayList<Long> prev = generateIDList();   
419
     
420
        node.mParent = null;  
421
        mChildren.remove(i);
422
        mNumChildren[0]--;
423
      
424
        RecomputeNodeID(prev);
425
      
426
        return true;
427
        }
428
      }
429
   
430
    return false;
431
    }
432
    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434
/**
435
 * Removes all children Nodes.
436
 */
437
  public synchronized void detachAll()
438
    {
439
    for(int i=0; i<mNumChildren[0]; i++)
440
      {
441
      mChildren.get(i).mParent = null;
442
      }
443
   
444
    if( mNumChildren[0]>0 )
445
      {
446
      ArrayList<Long> prev = generateIDList();  
447
      
448
      mNumChildren[0] = 0;
449
      mChildren.clear();
450
      RecomputeNodeID(prev);
451
      }
452
    }
453
  
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455
/**
456
 * Draws the Node, and all its children, to the default framebuffer 0 (i.e. the screen).
457
 *   
458
 * @param currTime Current time, in milliseconds.
459
 */
460
  public void draw(long currTime)
461
    {  
462
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
463
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
464
    GLES20.glUniform1i(Distorted.mTextureUniformH, 0);  
465
    
466
    markRecursive();
467
    drawRecursive(currTime,Distorted.mProjection,0);
468
    }
469
 
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471
/**
472
 * Returns the DistortedBitmap object that's in the Node.
473
 * 
474
 * @return The DistortedBitmap contained in the Node.
475
 */
476
  public DistortedBitmap getBitmap()
477
    {
478
    return mBitmap;  
479
    }
480
  
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482
// Debug - print all the Node IDs
483

  
484
  public void debug(int depth)
485
    {
486
    String tmp="";  
487
    int i;
488
   
489
    for(i=0; i<depth; i++) tmp +="   ";
490
    tmp += (""+mData.ID);
491
   
492
    android.util.Log.e("node", tmp);
493
   
494
    for(i=0; i<mNumChildren[0]; i++)
495
      mChildren.get(i).debug(depth+1);
496
    }
497

  
498
///////////////////////////////////////////////////////////////////////////////////////////////////
499
  }
500

  
src/main/java/org/distorted/library/DistortedObject.java
1
package org.distorted.library;
2

  
3
import android.graphics.Bitmap;
4
import android.opengl.GLES20;
5
import android.opengl.GLUtils;
6

  
7
///////////////////////////////////////////////////////////////////////////////////////////////////
8

  
9
public abstract class DistortedObject 
10
{ 
11
    static final int TYPE_NUM = 3;
12
    private static final int TYPE_MASK= (1<<TYPE_NUM)-1;
13
    private static float[] mViewMatrix = new float[16];
14
   
15
    protected EffectListMatrix   mM;
16
    protected EffectListFragment mF;
17
    protected EffectListVertex   mV;
18

  
19
    protected boolean matrixCloned, vertexCloned, fragmentCloned;
20
 
21
    protected GridObject mGrid = null;
22
    protected long mID;
23
    protected int mSizeX, mSizeY, mSizeZ, mSize; // in screen space
24

  
25
    protected Bitmap[] mBmp= null; // 
26
    int[] mTextureDataH;           // have to be shared among all the cloned Objects
27
    boolean[] mBitmapSet;          // 
28
 
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

  
31
    protected void initializeData(int size)
32
      {
33
      mID             = DistortedObjectList.add(this);
34
      mSize           = size;
35
      mTextureDataH   = new int[1];
36
      mTextureDataH[0]= 0;
37
      mBmp            = new Bitmap[1];
38
      mBmp[0]         = null;
39
      mBitmapSet      = new boolean[1];
40
      mBitmapSet[0]   = false;
41
      
42
      initializeEffectLists(this,0);
43
      
44
      if( Distorted.isInitialized() ) resetTexture();    
45
      }
46
    
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48
    
49
    protected void initializeEffectLists(DistortedObject d, int flags)
50
      {
51
      if( (flags & Distorted.CLONE_MATRIX) != 0 )
52
        {
53
        mM = d.mM;
54
        matrixCloned = true;
55
        } 
56
      else
57
        {
58
        mM = new EffectListMatrix(d);
59
        matrixCloned = false;  
60
        }
61
    
62
      if( (flags & Distorted.CLONE_VERTEX) != 0 )
63
        {
64
        mV = d.mV;
65
        vertexCloned = true;
66
        } 
67
      else
68
        {
69
        mV = new EffectListVertex(d);
70
        vertexCloned = false;  
71
        }
72
    
73
      if( (flags & Distorted.CLONE_FRAGMENT) != 0 )
74
        {
75
        mF = d.mF;
76
        fragmentCloned = true;
77
        } 
78
      else
79
        {
80
        mF = new EffectListFragment(d);
81
        fragmentCloned = false;   
82
        }
83
      }
84
    
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86
// this will be called on startup and every time OpenGL context has been lost
87
// also call this from the constructor if the OpenGL context has been created already.
88
    
89
    void resetTexture()
90
      {
91
      if( mTextureDataH!=null ) 
92
        {
93
        if( mTextureDataH[0]==0 ) GLES20.glGenTextures(1, mTextureDataH, 0);
94

  
95
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);       
96
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
97
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
98
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
99
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
100
       
101
        if( mBmp!=null && mBmp[0]!=null)
102
          {
103
          GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBmp[0], 0);
104
          mBmp[0] = null;
105
          }
106
        }
107
      }
108
  
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110
   
111
    void drawPriv(long currTime, DistortedProjection dp)
112
      {
113
      GLES20.glViewport(0, 0, dp.width, dp.height); 
114
      
115
      mM.compute(currTime);
116
      mM.send(mViewMatrix, dp);
117
      
118
      mV.compute(currTime);
119
      mV.postprocess();
120
      mV.send();
121
        
122
      mF.compute(currTime);
123
      mF.postprocess(mViewMatrix);
124
      mF.send();
125
       
126
      mGrid.draw();
127
      }
128

  
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130
   
131
    void drawNoEffectsPriv(DistortedProjection dp)
132
      {
133
      GLES20.glViewport(0, 0, dp.width, dp.height);
134
      mM.sendNoEffects(dp);
135
      mV.sendZero();
136
      mF.sendZero();
137
      mGrid.draw();
138
      }
139
    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141
   
142
    void releasePriv()
143
      {
144
      if( matrixCloned  ==false) mM.abortAll();
145
      if( vertexCloned  ==false) mV.abortAll();
146
      if( fragmentCloned==false) mF.abortAll();
147

  
148
      mBmp          = null;
149
      mGrid         = null;
150
      mM            = null;
151
      mV            = null;
152
      mF            = null;
153
      mTextureDataH = null;
154
      }
155
 
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

  
158
    long getBitmapID()
159
      {
160
      return mBmp==null ? 0 : mBmp.hashCode();
161
      }
162

  
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164
/**
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff