Project

General

Profile

« Previous | Next » 

Revision 4e2382f3

Added by Leszek Koltunski almost 8 years ago

Beginnings of split of DistortedObject into two separate classes: DistortedEffectQueues and DistortedTexture.

Still does not compile, but pushing already.

View differences:

src/main/java/org/distorted/library/Distorted.java
354 354
    GLES20.glEnableVertexAttribArray(mNormalH);
355 355
    GLES20.glEnableVertexAttribArray(mTextureCoordH);
356 356
   
357
    DistortedObject.reset();
357
    DistortedTexture.reset();
358 358
    DistortedObjectTree.reset();
359 359
    EffectMessageSender.startSending();
360 360
    }
......
379 379
 */
380 380
  public static void onDestroy()
381 381
    {
382
    DistortedObject.release();
382
    DistortedTexture.release();
383 383
    DistortedFramebuffer.release();
384 384
    DistortedObjectTree.release();
385 385
    EffectQueue.release();
src/main/java/org/distorted/library/DistortedEffectQueues.java
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.library;
21

  
22
import android.opengl.GLES20;
23

  
24
import org.distorted.library.message.EffectListener;
25
import org.distorted.library.type.Data1D;
26
import org.distorted.library.type.Data2D;
27
import org.distorted.library.type.Data3D;
28
import org.distorted.library.type.Data4D;
29
import org.distorted.library.type.Data5D;
30
import org.distorted.library.type.Static3D;
31

  
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33
/**
34
 * Class containing {@link EffectTypes#LENGTH} queues, each a class derived from EffectQueue.
35
 * <p>
36
 * The queues hold actual effects to be applied to a given (DistortedTexture,GridObject) combo.
37
 */
38
public class DistortedEffectQueues
39
  {
40
  private static long mNextID =0;
41
  private long mID;
42

  
43
  private EffectQueueMatrix    mM;
44
  private EffectQueueFragment  mF;
45
  private EffectQueueVertex    mV;
46

  
47
  private boolean matrixCloned, vertexCloned, fragmentCloned;
48

  
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50
    
51
  private void initializeEffectLists(DistortedEffectQueues d, int flags)
52
    {
53
    if( (flags & Distorted.CLONE_MATRIX) != 0 )
54
      {
55
      mM = d.mM;
56
      matrixCloned = true;
57
      }
58
    else
59
      {
60
      mM = new EffectQueueMatrix(mID);
61
      matrixCloned = false;
62
      }
63
    
64
    if( (flags & Distorted.CLONE_VERTEX) != 0 )
65
      {
66
      mV = d.mV;
67
      vertexCloned = true;
68
      }
69
    else
70
      {
71
      mV = new EffectQueueVertex(mID);
72
      vertexCloned = false;
73
      }
74
    
75
    if( (flags & Distorted.CLONE_FRAGMENT) != 0 )
76
      {
77
      mF = d.mF;
78
      fragmentCloned = true;
79
      }
80
    else
81
      {
82
      mF = new EffectQueueFragment(mID);
83
      fragmentCloned = false;
84
      }
85
    }
86

  
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88
   
89
  void drawPriv(long currTime, DistortedTexture tex, GridObject grid, DistortedFramebuffer df)
90
    {
91
    DistortedFramebuffer.deleteAllMarked();
92

  
93
    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
94

  
95
    mM.compute(currTime);
96
    mM.send(df,tex.mHalfX,tex.mHalfY,tex.mHalfZ);
97
      
98
    mV.compute(currTime);
99
    mV.send(tex.mHalfX,tex.mHalfY,tex.mHalfZ);
100
        
101
    mF.compute(currTime);
102
    mF.send(tex.mHalfX,tex.mHalfY);
103

  
104
    grid.draw();
105
    }
106

  
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108
   
109
  void drawNoEffectsPriv(DistortedTexture tex, GridObject grid, DistortedFramebuffer df)
110
    {
111
    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
112

  
113
    mM.sendZero(df,tex.mHalfX,tex.mHalfY,tex.mHalfZ);
114
    mV.sendZero();
115
    mF.sendZero();
116

  
117
    grid.draw();
118
    }
119
    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121
   
122
  private void releasePriv()
123
    {
124
    if( !matrixCloned  ) mM.abortAll(false);
125
    if( !vertexCloned  ) mV.abortAll(false);
126
    if( !fragmentCloned) mF.abortAll(false);
127

  
128
    mM = null;
129
    mV = null;
130
    mF = null;
131
    }
132

  
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134
// PUBLIC API
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136
/**
137
 * Create empty effect queue.
138
 */
139
  public DistortedEffectQueues()
140
    {
141
    mID = mNextID++;
142
    initializeEffectLists(this,0);
143
    }
144

  
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146
/**
147
 * Copy constructor.
148
 * <p>
149
 * Whatever we do not clone gets created just like in the default constructor.
150
 * We only call this from the descendant's classes' constructors where we have to pay attention
151
 * to give it the appropriate type of a DistortedObject!
152
 *
153
 * @param dc    Source object to create our object from
154
 * @param flags A bitmask of values specifying what to copy.
155
 *              For example, CLONE_BITMAP | CLONE_MATRIX.
156
 */
157
  public DistortedEffectQueues(DistortedEffectQueues dc, int flags)
158
    {
159
    mID = mNextID++;
160
    initializeEffectLists(dc,flags);
161
    }
162

  
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164
/**
165
 * Draw the DistortedObject to the location specified by current Matrix effects.    
166
 *     
167
 * @param currTime current time, in milliseconds.
168
 *        This gets passed on to Dynamics inside the Effects that are currently applied to the
169
 *        Object.
170
 */
171
  public void draw(long currTime, DistortedTexture tex, GridObject grid)
172
    {
173
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
174
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.mTextureDataH[0]);
175
    drawPriv(currTime, tex, grid, Distorted.mFramebuffer);
176
    }
177

  
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179
/**
180
 * Draw the DistortedObject to the Framebuffer passed.
181
 *
182
 * @param currTime Current time, in milliseconds.
183
 * @param df       Framebuffer to render this to.
184
 */
185
  public void draw(long currTime, DistortedTexture tex, GridObject grid, DistortedFramebuffer df)
186
    {
187
    df.setAsOutput();
188
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.mTextureDataH[0]);
189
    drawPriv(currTime, tex, grid, df);
190
    }
191

  
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193
/**
194
 * Releases all resources.
195
 */
196
  public synchronized void delete()
197
    {
198
    releasePriv();
199
    }
200

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
/**
203
 * Returns unique ID of this instance.
204
 *
205
 * @return ID of the object.
206
 */
207
  public long getID()
208
      {
209
      return mID;
210
      }
211

  
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
/**
214
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
215
 * to one of the Effects that are currently applied to the DistortedObject.
216
 * 
217
 * @param el A class implementing the EffectListener interface that wants to get notifications.
218
 */
219
  public void addEventListener(EffectListener el)
220
    {
221
    mV.addListener(el);
222
    mF.addListener(el);
223
    mM.addListener(el);
224
    }
225

  
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
/**
228
 * Removes the calling class from the list of Listeners.
229
 * 
230
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
231
 */
232
  public void removeEventListener(EffectListener el)
233
    {
234
    mV.removeListener(el);
235
    mF.removeListener(el);
236
    mM.removeListener(el);
237
    }
238

  
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
/**
241
 * Aborts all Effects.
242
 * @return Number of effects aborted.
243
 */
244
  public int abortAllEffects()
245
      {
246
      return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
247
      }
248

  
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250
/**
251
 * Aborts all Effects of a given type, for example all MATRIX Effects.
252
 * 
253
 * @param type one of the constants defined in {@link EffectTypes}
254
 * @return Number of effects aborted.
255
 */
256
  public int abortEffects(EffectTypes type)
257
    {
258
    switch(type)
259
      {
260
      case MATRIX  : return mM.abortAll(true);
261
      case VERTEX  : return mV.abortAll(true);
262
      case FRAGMENT: return mF.abortAll(true);
263
      default      : return 0;
264
      }
265
    }
266
    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268
/**
269
 * Aborts a single Effect.
270
 * 
271
 * @param id ID of the Effect we want to abort.
272
 * @return number of Effects aborted. Always either 0 or 1.
273
 */
274
  public int abortEffect(long id)
275
    {
276
    int type = (int)(id&EffectTypes.MASK);
277

  
278
    if( type==EffectTypes.MATRIX.type   ) return mM.removeByID(id>>EffectTypes.LENGTH);
279
    if( type==EffectTypes.VERTEX.type   ) return mV.removeByID(id>>EffectTypes.LENGTH);
280
    if( type==EffectTypes.FRAGMENT.type ) return mF.removeByID(id>>EffectTypes.LENGTH);
281

  
282
    return 0;
283
    }
284

  
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286
/**
287
 * Abort all Effects of a given name, for example all rotations.
288
 * 
289
 * @param name one of the constants defined in {@link EffectNames}
290
 * @return number of Effects aborted.
291
 */
292
  public int abortEffects(EffectNames name)
293
    {
294
    switch(name.getType())
295
      {
296
      case MATRIX  : return mM.removeByType(name);
297
      case VERTEX  : return mV.removeByType(name);
298
      case FRAGMENT: return mF.removeByType(name);
299
      default      : return 0;
300
      }
301
    }
302
    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304
/**
305
 * Print some info about a given Effect to Android's standard out. Used for debugging only.
306
 * 
307
 * @param id Effect ID we want to print info about
308
 * @return <code>true</code> if a single Effect of type effectType has been found.
309
 */
310
    
311
  public boolean printEffect(long id)
312
    {
313
    int type = (int)(id&EffectTypes.MASK);
314

  
315
    if( type==EffectTypes.MATRIX.type   )  return mM.printByID(id>>EffectTypes.LENGTH);
316
    if( type==EffectTypes.VERTEX.type   )  return mV.printByID(id>>EffectTypes.LENGTH);
317
    if( type==EffectTypes.FRAGMENT.type )  return mF.printByID(id>>EffectTypes.LENGTH);
318

  
319
    return false;
320
    }
321
   
322
///////////////////////////////////////////////////////////////////////////////////////////////////   
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324
// Individual effect functions.
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326
// Matrix-based effects
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328
/**
329
 * Moves the Object by a (possibly changing in time) vector.
330
 * 
331
 * @param vector 3-dimensional Data which at any given time will return a Static3D
332
 *               representing the current coordinates of the vector we want to move the Object with.
333
 * @return       ID of the effect added, or -1 if we failed to add one.
334
 */
335
  public long move(Data3D vector)
336
    {   
337
    return mM.add(EffectNames.MOVE,vector);
338
    }
339

  
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341
/**
342
 * Scales the Object by (possibly changing in time) 3D scale factors.
343
 * 
344
 * @param scale 3-dimensional Data which at any given time returns a Static3D
345
 *              representing the current x- , y- and z- scale factors.
346
 * @return      ID of the effect added, or -1 if we failed to add one.
347
 */
348
  public long scale(Data3D scale)
349
    {   
350
    return mM.add(EffectNames.SCALE,scale);
351
    }
352

  
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354
/**
355
 * Scales the Object by one uniform, constant factor in all 3 dimensions. Convenience function.
356
 *
357
 * @param scale The factor to scale all 3 dimensions with.
358
 * @return      ID of the effect added, or -1 if we failed to add one.
359
 */
360
  public long scale(float scale)
361
    {
362
    return mM.add(EffectNames.SCALE, new Static3D(scale,scale,scale));
363
    }
364

  
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366
/**
367
 * Rotates the Object by 'angle' degrees around the center.
368
 * Static axis of rotation is given by the last parameter.
369
 *
370
 * @param angle  Angle that we want to rotate the Object to. Unit: degrees
371
 * @param axis   Axis of rotation
372
 * @param center Coordinates of the Point we are rotating around.
373
 * @return       ID of the effect added, or -1 if we failed to add one.
374
 */
375
  public long rotate(Data1D angle, Static3D axis, Data3D center )
376
    {   
377
    return mM.add(EffectNames.ROTATE, angle, axis, center);
378
    }
379

  
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381
/**
382
 * Rotates the Object by 'angle' degrees around the center.
383
 * Here both angle and axis can dynamically change.
384
 *
385
 * @param angleaxis Combined 4-tuple representing the (angle,axisX,axisY,axisZ).
386
 * @param center    Coordinates of the Point we are rotating around.
387
 * @return          ID of the effect added, or -1 if we failed to add one.
388
 */
389
  public long rotate(Data4D angleaxis, Data3D center)
390
    {
391
    return mM.add(EffectNames.ROTATE, angleaxis, center);
392
    }
393

  
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
/**
396
 * Rotates the Object by quaternion.
397
 *
398
 * @param quaternion The quaternion describing the rotation.
399
 * @param center     Coordinates of the Point we are rotating around.
400
 * @return           ID of the effect added, or -1 if we failed to add one.
401
 */
402
  public long quaternion(Data4D quaternion, Data3D center )
403
    {
404
    return mM.add(EffectNames.QUATERNION,quaternion,center);
405
    }
406

  
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408
/**
409
 * Shears the Object.
410
 *
411
 * @param shear   The 3-tuple of shear factors. The first controls level
412
 *                of shearing in the X-axis, second - Y-axis and the third -
413
 *                Z-axis. Each is the tangens of the shear angle, i.e 0 -
414
 *                no shear, 1 - shear by 45 degrees (tan(45deg)=1) etc.
415
 * @param center  Center of shearing, i.e. the point which stays unmoved.
416
 * @return        ID of the effect added, or -1 if we failed to add one.
417
 */
418
  public long shear(Data3D shear, Data3D center)
419
    {
420
    return mM.add(EffectNames.SHEAR, shear, center);
421
    }
422

  
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424
// Fragment-based effects  
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426
/**
427
 * Makes a certain sub-region of the Object smoothly change all three of its RGB components.
428
 *        
429
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
430
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color.
431
 *               Valid range: <0,1>
432
 * @param color  Color to mix. (1,0,0) is RED.
433
 * @param region Region this Effect is limited to.
434
 * @param smooth If true, the level of 'blend' will smoothly fade out towards the edges of the region.
435
 * @return       ID of the effect added, or -1 if we failed to add one.
436
 */
437
  public long chroma(Data1D blend, Data3D color, Data4D region, boolean smooth)
438
    {
439
    return mF.add( smooth? EffectNames.SMOOTH_CHROMA:EffectNames.CHROMA, blend, color, region);
440
    }
441

  
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443
/**
444
 * Makes the whole Object smoothly change all three of its RGB components.
445
 *
446
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
447
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color.
448
 *               Valid range: <0,1>
449
 * @param color  Color to mix. (1,0,0) is RED.
450
 * @return       ID of the effect added, or -1 if we failed to add one.
451
 */
452
  public long chroma(Data1D blend, Data3D color)
453
    {
454
    return mF.add(EffectNames.CHROMA, blend, color);
455
    }
456

  
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458
/**
459
 * Makes a certain sub-region of the Object smoothly change its transparency level.
460
 *        
461
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any given
462
 *               moment: pixel.a *= alpha.
463
 *               Valid range: <0,1>
464
 * @param region Region this Effect is limited to. 
465
 * @param smooth If true, the level of 'alpha' will smoothly fade out towards the edges of the region.
466
 * @return       ID of the effect added, or -1 if we failed to add one. 
467
 */
468
  public long alpha(Data1D alpha, Data4D region, boolean smooth)
469
    {
470
    return mF.add( smooth? EffectNames.SMOOTH_ALPHA:EffectNames.ALPHA, alpha, region);
471
    }
472

  
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474
/**
475
 * Makes the whole Object smoothly change its transparency level.
476
 *
477
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any
478
 *               given moment: pixel.a *= alpha.
479
 *               Valid range: <0,1>
480
 * @return       ID of the effect added, or -1 if we failed to add one.
481
 */
482
  public long alpha(Data1D alpha)
483
    {
484
    return mF.add(EffectNames.ALPHA, alpha);
485
    }
486

  
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488
/**
489
 * Makes a certain sub-region of the Object smoothly change its brightness level.
490
 *        
491
 * @param brightness 1-dimensional Data that returns the level of brightness we want to have
492
 *                   at any given moment. Valid range: <0,infinity)
493
 * @param region     Region this Effect is limited to.
494
 * @param smooth     If true, the level of 'brightness' will smoothly fade out towards the edges of the region.
495
 * @return           ID of the effect added, or -1 if we failed to add one.
496
 */
497
  public long brightness(Data1D brightness, Data4D region, boolean smooth)
498
    {
499
    return mF.add( smooth ? EffectNames.SMOOTH_BRIGHTNESS: EffectNames.BRIGHTNESS, brightness, region);
500
    }
501

  
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503
/**
504
 * Makes the whole Object smoothly change its brightness level.
505
 *
506
 * @param brightness 1-dimensional Data that returns the level of brightness we want to have
507
 *                   at any given moment. Valid range: <0,infinity)
508
 * @return           ID of the effect added, or -1 if we failed to add one.
509
 */
510
  public long brightness(Data1D brightness)
511
    {
512
    return mF.add(EffectNames.BRIGHTNESS, brightness);
513
    }
514

  
515
///////////////////////////////////////////////////////////////////////////////////////////////////
516
/**
517
 * Makes a certain sub-region of the Object smoothly change its contrast level.
518
 *        
519
 * @param contrast 1-dimensional Data that returns the level of contrast we want to have
520
 *                 at any given moment. Valid range: <0,infinity)
521
 * @param region   Region this Effect is limited to.
522
 * @param smooth   If true, the level of 'contrast' will smoothly fade out towards the edges of the region.
523
 * @return         ID of the effect added, or -1 if we failed to add one.
524
 */
525
  public long contrast(Data1D contrast, Data4D region, boolean smooth)
526
    {
527
    return mF.add( smooth ? EffectNames.SMOOTH_CONTRAST:EffectNames.CONTRAST, contrast, region);
528
    }
529

  
530
///////////////////////////////////////////////////////////////////////////////////////////////////
531
/**
532
 * Makes the whole Object smoothly change its contrast level.
533
 *
534
 * @param contrast 1-dimensional Data that returns the level of contrast we want to have
535
 *                 at any given moment. Valid range: <0,infinity)
536
 * @return         ID of the effect added, or -1 if we failed to add one.
537
 */
538
  public long contrast(Data1D contrast)
539
    {
540
    return mF.add(EffectNames.CONTRAST, contrast);
541
    }
542

  
543
///////////////////////////////////////////////////////////////////////////////////////////////////
544
/**
545
 * Makes a certain sub-region of the Object smoothly change its saturation level.
546
 *        
547
 * @param saturation 1-dimensional Data that returns the level of saturation we want to have
548
 *                   at any given moment. Valid range: <0,infinity)
549
 * @param region     Region this Effect is limited to.
550
 * @param smooth     If true, the level of 'saturation' will smoothly fade out towards the edges of the region.
551
 * @return           ID of the effect added, or -1 if we failed to add one.
552
 */
553
  public long saturation(Data1D saturation, Data4D region, boolean smooth)
554
    {
555
    return mF.add( smooth ? EffectNames.SMOOTH_SATURATION:EffectNames.SATURATION, saturation, region);
556
    }
557

  
558
///////////////////////////////////////////////////////////////////////////////////////////////////
559
/**
560
 * Makes the whole Object smoothly change its saturation level.
561
 *
562
 * @param saturation 1-dimensional Data that returns the level of saturation we want to have
563
 *                   at any given moment. Valid range: <0,infinity)
564
 * @return           ID of the effect added, or -1 if we failed to add one.
565
 */
566
  public long saturation(Data1D saturation)
567
    {
568
    return mF.add(EffectNames.SATURATION, saturation);
569
    }
570

  
571
///////////////////////////////////////////////////////////////////////////////////////////////////
572
// Vertex-based effects  
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574
/**
575
 * Distort a (possibly changing in time) part of the Object by a (possibly changing in time) vector of force.
576
 *
577
 * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
578
 *               currently being dragged with.
579
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
580
 * @param region Region that masks the Effect.
581
 * @return       ID of the effect added, or -1 if we failed to add one.
582
 */
583
  public long distort(Data3D vector, Data3D center, Data4D region)
584
    {  
585
    return mV.add(EffectNames.DISTORT, vector, center, region);
586
    }
587

  
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589
/**
590
 * Distort the whole Object by a (possibly changing in time) vector of force.
591
 *
592
 * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
593
 *               currently being dragged with.
594
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
595
 * @return       ID of the effect added, or -1 if we failed to add one.
596
 */
597
  public long distort(Data3D vector, Data3D center)
598
    {
599
    return mV.add(EffectNames.DISTORT, vector, center, null);
600
    }
601

  
602
///////////////////////////////////////////////////////////////////////////////////////////////////
603
/**
604
 * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
605
 * a (possibly changing in time) point on the Object.
606
 *
607
 * @param vector Vector of force that deforms the shape of the whole Object.
608
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
609
 * @param region Region that masks the Effect.
610
 * @return       ID of the effect added, or -1 if we failed to add one.
611
 */
612
  public long deform(Data3D vector, Data3D center, Data4D region)
613
    {
614
    return mV.add(EffectNames.DEFORM, vector, center, region);
615
    }
616

  
617
///////////////////////////////////////////////////////////////////////////////////////////////////
618
/**
619
 * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
620
 * a (possibly changing in time) point on the Object.
621
 *     
622
 * @param vector Vector of force that deforms the shape of the whole Object.
623
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
624
 * @return       ID of the effect added, or -1 if we failed to add one.
625
 */
626
  public long deform(Data3D vector, Data3D center)
627
    {  
628
    return mV.add(EffectNames.DEFORM, vector, center, null);
629
    }
630

  
631
///////////////////////////////////////////////////////////////////////////////////////////////////  
632
/**
633
 * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
634
 * away from the center (degree<=1)
635
 *
636
 * @param sink   The current degree of the Effect.
637
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
638
 * @param region Region that masks the Effect.
639
 * @return       ID of the effect added, or -1 if we failed to add one.
640
 */
641
  public long sink(Data1D sink, Data3D center, Data4D region)
642
    {
643
    return mV.add(EffectNames.SINK, sink, center, region);
644
    }
645

  
646
///////////////////////////////////////////////////////////////////////////////////////////////////
647
/**
648
 * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
649
 * away from the center (degree<=1)
650
 *
651
 * @param sink   The current degree of the Effect.
652
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
653
 * @return       ID of the effect added, or -1 if we failed to add one.
654
 */
655
  public long sink(Data1D sink, Data3D center)
656
    {
657
    return mV.add(EffectNames.SINK, sink, center);
658
    }
659

  
660
///////////////////////////////////////////////////////////////////////////////////////////////////
661
/**
662
 * Pull all points around the center of the Effect towards a line passing through the center
663
 * (that's if degree>=1) or push them away from the line (degree<=1)
664
 *
665
 * @param pinch  The current degree of the Effect + angle the line forms with X-axis
666
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
667
 * @param region Region that masks the Effect.
668
 * @return       ID of the effect added, or -1 if we failed to add one.
669
 */
670
  public long pinch(Data2D pinch, Data3D center, Data4D region)
671
    {
672
    return mV.add(EffectNames.PINCH, pinch, center, region);
673
    }
674

  
675
///////////////////////////////////////////////////////////////////////////////////////////////////
676
/**
677
 * Pull all points around the center of the Effect towards a line passing through the center
678
 * (that's if degree>=1) or push them away from the line (degree<=1)
679
 *
680
 * @param pinch  The current degree of the Effect + angle the line forms with X-axis
681
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
682
 * @return       ID of the effect added, or -1 if we failed to add one.
683
 */
684
  public long pinch(Data2D pinch, Data3D center)
685
    {
686
    return mV.add(EffectNames.PINCH, pinch, center);
687
    }
688

  
689
///////////////////////////////////////////////////////////////////////////////////////////////////  
690
/**
691
 * Rotate part of the Object around the Center of the Effect by a certain angle.
692
 *
693
 * @param swirl  The angle of Swirl (in degrees). Positive values swirl clockwise.
694
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
695
 * @param region Region that masks the Effect.
696
 * @return       ID of the effect added, or -1 if we failed to add one.
697
 */
698
  public long swirl(Data1D swirl, Data3D center, Data4D region)
699
    {    
700
    return mV.add(EffectNames.SWIRL, swirl, center, region);
701
    }
702

  
703
///////////////////////////////////////////////////////////////////////////////////////////////////
704
/**
705
 * Rotate the whole Object around the Center of the Effect by a certain angle.
706
 *
707
 * @param swirl  The angle of Swirl (in degrees). Positive values swirl clockwise.
708
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
709
 * @return       ID of the effect added, or -1 if we failed to add one.
710
 */
711
  public long swirl(Data1D swirl, Data3D center)
712
    {
713
    return mV.add(EffectNames.SWIRL, swirl, center);
714
    }
715

  
716
///////////////////////////////////////////////////////////////////////////////////////////////////
717
/**
718
 * Directional, sinusoidal wave effect.
719
 *
720
 * @param wave   A 5-dimensional data structure describing the wave: first member is the amplitude,
721
 *               second is the wave length, third is the phase (i.e. when phase = PI/2, the sine
722
 *               wave at the center does not start from sin(0), but from sin(PI/2) ) and the next two
723
 *               describe the 'direction' of the wave.
724
 *               <p>
725
 *               Wave direction is defined to be a 3D vector of length 1. To define such vectors, we
726
 *               need 2 floats: thus the third member is the angle Alpha (in degrees) which the vector
727
 *               forms with the XY-plane, and the fourth is the angle Beta (again in degrees) which
728
 *               the projection of the vector to the XY-plane forms with the Y-axis (counterclockwise).
729
 *               <p>
730
 *               <p>
731
 *               Example1: if Alpha = 90, Beta = 90, (then V=(0,0,1) ) and the wave acts 'vertically'
732
 *               in the X-direction, i.e. cross-sections of the resulting surface with the XZ-plane
733
 *               will be sine shapes.
734
 *               <p>
735
 *               Example2: if Alpha = 90, Beta = 0, the again V=(0,0,1) and the wave is 'vertical',
736
 *               but this time it waves in the Y-direction, i.e. cross sections of the surface and the
737
 *               YZ-plane with be sine shapes.
738
 *               <p>
739
 *               Example3: if Alpha = 0 and Beta = 45, then V=(sqrt(2)/2, -sqrt(2)/2, 0) and the wave
740
 *               is entirely 'horizontal' and moves point (x,y,0) in direction V by whatever is the
741
 *               value if sin at this point.
742
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
743
 * @return       ID of the effect added, or -1 if we failed to add one.
744
 */
745
  public long wave(Data5D wave, Data3D center)
746
    {
747
    return mV.add(EffectNames.WAVE, wave, center, null);
748
    }
749

  
750
///////////////////////////////////////////////////////////////////////////////////////////////////
751
/**
752
 * Directional, sinusoidal wave effect.
753
 *
754
 * @param wave   see {@link DistortedObject#wave(Data5D,Data3D)}
755
 * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
756
 * @param region Region that masks the Effect.
757
 * @return       ID of the effect added, or -1 if we failed to add one.
758
 */
759
  public long wave(Data5D wave, Data3D center, Data4D region)
760
    {
761
    return mV.add(EffectNames.WAVE, wave, center, region);
762
    }
763
  }
src/main/java/org/distorted/library/DistortedObject.java
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.library;
21

  
22
import android.graphics.Bitmap;
23
import android.graphics.Matrix;
24
import android.opengl.GLES20;
25
import android.opengl.GLUtils;
26

  
27
import org.distorted.library.message.EffectListener;
28
import org.distorted.library.type.Data1D;
29
import org.distorted.library.type.Data2D;
30
import org.distorted.library.type.Data3D;
31
import org.distorted.library.type.Data4D;
32
import org.distorted.library.type.Data5D;
33
import org.distorted.library.type.Static3D;
34

  
35
import java.util.HashMap;
36

  
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38
/**
39
 * All Objects to which Distorted Graphics effects can be applied need to be extended from here.
40
 * <p>
41
 * General idea is as follows:
42
 * <ul>
43
 * <li> Create an instance of (some class descended from) DistortedObject
44
 * <li> Paint something onto the Bitmap that's backing it up
45
 * <li> Apply some effects
46
 * <li> Draw it!
47
 * </ul>
48
 * <p>
49
 * The effects we can apply fall into three general categories:
50
 * <ul>
51
 * <li> Matrix Effects, i.e. ones that change the Bitmap's ModelView Matrix (moves, scales, rotations)
52
 * <li> Vertex Effects, i.e. effects that are implemented in the Vertex Shader. Those typically change
53
 *      the shape of (some sub-Region of) the Bitmap in some way (deforms, distortions, sinks)
54
 * <li> Fragment Effects, i.e. effects that change (some of) the pixels of the Bitmap (transparency, macroblock)
55
 * </ul>
56
 * <p>
57
 * Just like in DistortedObjectTree and DistortedFramebuffer, we need to have a static list of all
58
 * DistortedObjects currently created by the application so that we can implement the 'mark for
59
 * deletion now - actually delete on next render' thing.
60
 * We need to be able to quickly retrieve an Object by its ID, thus a HashMap.
61
 */
62
public class DistortedObject
63
  {
64
  private static long mNextID =0;
65
  private static HashMap<Long,DistortedObject> mObjects = new HashMap<>();
66

  
67
  private EffectQueueMatrix    mM;
68
  private EffectQueueFragment  mF;
69
  private EffectQueueVertex    mV;
70

  
71
  private boolean matrixCloned, vertexCloned, fragmentCloned;
72
  private long mID;
73
  private int mSizeX, mSizeY, mSizeZ;   // in screen space
74
  private float mHalfX, mHalfY, mHalfZ; // halves of the above
75

  
76
  private Bitmap[] mBmp= null; //
77
  int[] mTextureDataH;         // have to be shared among all the cloned Objects
78
  boolean[] mBitmapSet;        //
79

  
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81
// We have to flip vertically every single Bitmap that we get fed with.
82
//
83
// Reason: textures read from files are the only objects in OpenGL which have their origins at the
84
// upper-left corner. Everywhere else the origin is in the lower-left corner. Thus we have to flip.
85
// The alternative solution, namely inverting the y-coordinate of the TexCoord does not really work-
86
// i.e. it works only in case of rendering directly to the screen, but if we render to an FBO and
87
// then take the FBO and render to screen, (DistortedObjectTree does so!) things get inverted as textures
88
// created from FBO have their origins in the lower-left... Mindfuck!
89

  
90
  private static Bitmap flipBitmap(Bitmap src)
91
    {
92
    Matrix matrix = new Matrix();
93
    matrix.preScale(1.0f,-1.0f);
94

  
95
    return Bitmap.createBitmap(src,0,0,src.getWidth(),src.getHeight(), matrix,true);
96
    }
97

  
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

  
100
  private void initializeData(int x, int y, int z)
101
    {
102
    mSizeX= x; mHalfX = x/2.0f;
103
    mSizeY= y; mHalfY = y/2.0f;
104
    mSizeZ= z; mHalfZ = z/2.0f;
105

  
106
    mID = mNextID++;
107
    mObjects.put(mID,this);
108

  
109
    mTextureDataH   = new int[1];
110
    mTextureDataH[0]= 0;
111
    mBmp            = new Bitmap[1];
112
    mBmp[0]         = null;
113
    mBitmapSet      = new boolean[1];
114
    mBitmapSet[0]   = false;
115
      
116
    initializeEffectLists(this,0);
117
      
118
    if( Distorted.isInitialized() ) resetTexture();
119
    }
120
    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
    
123
  private void initializeEffectLists(DistortedObject d, int flags)
124
    {
125
    long objID = d.getID();
126

  
127
    if( (flags & Distorted.CLONE_MATRIX) != 0 )
128
      {
129
      mM = d.mM;
130
      matrixCloned = true;
131
      }
132
    else
133
      {
134
      mM = new EffectQueueMatrix(objID);
135
      matrixCloned = false;
136
      }
137
    
138
    if( (flags & Distorted.CLONE_VERTEX) != 0 )
139
      {
140
      mV = d.mV;
141
      vertexCloned = true;
142
      }
143
    else
144
      {
145
      mV = new EffectQueueVertex(objID);
146
      vertexCloned = false;
147
      }
148
    
149
    if( (flags & Distorted.CLONE_FRAGMENT) != 0 )
150
      {
151
      mF = d.mF;
152
      fragmentCloned = true;
153
      }
154
    else
155
      {
156
      mF = new EffectQueueFragment(objID);
157
      fragmentCloned = false;
158
      }
159
    }
160
    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
// this will be called on startup and every time OpenGL context has been lost
163
// also call this from the constructor if the OpenGL context has been created already.
164
    
165
  private void resetTexture()
166
    {
167
    if( mTextureDataH!=null )
168
      {
169
      if( mTextureDataH[0]==0 ) GLES20.glGenTextures(1, mTextureDataH, 0);
170

  
171
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
172
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
173
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
174
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
175
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
176
       
177
      if( mBmp!=null && mBmp[0]!=null)
178
        {
179
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, flipBitmap(mBmp[0]), 0);
180
        mBmp[0] = null;
181
        }
182
      }
183
    }
184
  
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
   
187
  void drawPriv(long currTime, GridObject grid, DistortedFramebuffer df)
188
    {
189
    DistortedFramebuffer.deleteAllMarked();
190

  
191
    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
192

  
193
    mM.compute(currTime);
194
    mM.send(df,mHalfX,mHalfY,mHalfZ);
195
      
196
    mV.compute(currTime);
197
    mV.send(mHalfX,mHalfY,mHalfZ);
198
        
199
    mF.compute(currTime);
200
    mF.send(mHalfX,mHalfY);
201

  
202
    grid.draw();
203
    }
204

  
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
   
207
  void drawNoEffectsPriv(GridObject grid, DistortedFramebuffer df)
208
    {
209
    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
210

  
211
    mM.sendZero(df,mHalfX,mHalfY,mHalfZ);
212
    mV.sendZero();
213
    mF.sendZero();
214

  
215
    grid.draw();
216
    }
217
    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219
   
220
  private void releasePriv()
221
    {
222
    if( !matrixCloned  ) mM.abortAll(false);
223
    if( !vertexCloned  ) mV.abortAll(false);
224
    if( !fragmentCloned) mF.abortAll(false);
225

  
226
    mBmp          = null;
227
    mM            = null;
228
    mV            = null;
229
    mF            = null;
230
    mTextureDataH = null;
231
    }
232
 
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

  
235
  long getBitmapID()
236
    {
237
    return mBmp==null ? 0 : mBmp.hashCode();
238
    }
239

  
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

  
242
  static synchronized void reset()
243
    {
244
    for(long id: mObjects.keySet())
245
      {
246
      mObjects.get(id).resetTexture();
247
      }
248
    }
249

  
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

  
252
  static synchronized void release()
253
    {
254
    for(long id: mObjects.keySet())
255
      {
256
      mObjects.get(id).releasePriv();
257
      }
258

  
259
    mObjects.clear();
260
    mNextID = 0;
261
    }
262

  
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264
// PUBLIC API
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266
/**
267
 * Create empty effect queue with no Bitmap.
268
 */
269
  public DistortedObject(int width, int height, int depth)
270
    {
271
    initializeData(width,height,depth);
272
    }
273

  
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
/**
276
 * Copy constructor used to create a DistortedObject based on various parts of another object.
277
 * <p>
278
 * Whatever we do not clone gets created just like in the default constructor.
279
 * We only call this from the descendant's classes' constructors where we have to pay attention
280
 * to give it the appropriate type of a DistortedObject!
281
 *
282
 * @param dc    Source object to create our object from
283
 * @param flags A bitmask of values specifying what to copy.
284
 *              For example, CLONE_BITMAP | CLONE_MATRIX.
285
 */
286
  public DistortedObject(DistortedObject dc, int flags)
287
    {
288
    initializeEffectLists(dc,flags);
289

  
290
    mID = mNextID++;
291
    mObjects.put(mID,this);
292

  
293
    mSizeX = dc.mSizeX;
294
    mSizeY = dc.mSizeY;
295
    mSizeZ = dc.mSizeZ;
296
    mHalfX = dc.mHalfX;
297
    mHalfY = dc.mHalfY;
298
    mHalfZ = dc.mHalfZ;
299

  
300
    if( (flags & Distorted.CLONE_BITMAP) != 0 )
301
      {
302
      mTextureDataH = dc.mTextureDataH;
303
      mBmp          = dc.mBmp;
304
      mBitmapSet    = dc.mBitmapSet;
305
      }
306
    else
307
      {
308
      mTextureDataH   = new int[1];
309
      mTextureDataH[0]= 0;
310
      mBitmapSet      = new boolean[1];
311
      mBitmapSet[0]   = false;
312
      mBmp            = new Bitmap[1];
313
      mBmp[0]         = null;
314

  
315
      if( Distorted.isInitialized() ) resetTexture();
316
      }
317
    }
318

  
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320
/**
321
 * Draw the DistortedObject to the location specified by current Matrix effects.    
322
 *     
323
 * @param currTime current time, in milliseconds.
324
 *        This gets passed on to Dynamics inside the Effects that are currently applied to the
325
 *        Object.
326
 */
327
  public void draw(long currTime, GridObject grid)
328
    {
329
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
330
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
331
    drawPriv(currTime, grid, Distorted.mFramebuffer);
332
    }
333

  
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335
/**
336
 * Draw the DistortedObject to the Framebuffer passed.
337
 *
338
 * @param currTime Current time, in milliseconds.
339
 * @param df       Framebuffer to render this to.
340
 */
341
  public void draw(long currTime, GridObject grid, DistortedFramebuffer df)
342
    {
343
    df.setAsOutput();
344
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
345
    drawPriv(currTime,grid, df);
346
    }
347

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349
/**
350
 * Releases all resources.
351
 */
352
  public synchronized void delete()
353
    {
354
    releasePriv();
355
    mObjects.remove(this);
356
    }
357

  
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359
/**
360
 * Sets the underlying android.graphics.Bitmap object and uploads it to the GPU. 
361
 * <p>
362
 * You can only recycle() the passed Bitmap once the OpenGL context gets created (i.e. after call 
363
 * to onSurfaceCreated) because only after this point can the Library upload it to the GPU!
364
 * 
365
 * @param bmp The android.graphics.Bitmap object to apply effects to and display.
366
 */
367
   
368
  public void setTexture(Bitmap bmp)
369
    {
370
    mBitmapSet[0] = true;
371
/*
372
    mSizeX= bmp.getWidth() ; mHalfX = mSizeX/2;
373
    mSizeY= bmp.getHeight(); mHalfY = mSizeY/2;
374
*/
375
    if( Distorted.isInitialized() )
376
      {
377
      GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
378
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
379
      GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, flipBitmap(bmp), 0);
380
      }
381
    else
382
      {
383
      mBmp[0] = bmp;
384
      }
385
    }
386
    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388
/**
389
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
390
 * to one of the Effects that are currently applied to the DistortedObject.
391
 * 
392
 * @param el A class implementing the EffectListener interface that wants to get notifications.
393
 */
394
  public void addEventListener(EffectListener el)
395
    {
396
    mV.addListener(el);
397
    mF.addListener(el);
398
    mM.addListener(el);
399
    }
400

  
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402
/**
403
 * Removes the calling class from the list of Listeners.
404
 * 
405
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
406
 */
407
  public void removeEventListener(EffectListener el)
408
    {
409
    mV.removeListener(el);
410
    mF.removeListener(el);
411
    mM.removeListener(el);
412
    }
413
   
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415
/**
416
 * Returns the height of the DistortedObject.
417
 *    
418
 * @return height of the object, in pixels.
419
 */
420
  public int getWidth()
421
     {
422
     return mSizeX;   
423
     }
424

  
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426
/**
427
 * Returns the width of the DistortedObject.
428
 * 
429
 * @return width of the Object, in pixels.
430
 */
431
  public int getHeight()
432
      {
433
      return mSizeY;  
434
      }
435
    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437
/**
438
 * Returns the depth of the DistortedObject.
439
 * 
440
 * @return depth of the Object, in pixels.
441
 */
442
  public int getDepth()
443
      {
444
      return mSizeZ;  
445
      }
446
        
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448
/**
449
 * Returns unique ID of this instance.
450
 * 
451
 * @return ID of the object.
452
 */
453
  public long getID()
454
      {
455
      return mID;  
456
      }
457
    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459
/**
460
 * Aborts all Effects.
461
 * @return Number of effects aborted.
462
 */
463
  public int abortAllEffects()
464
      {
465
      return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
466
      }
467

  
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469
/**
470
 * Aborts all Effects of a given type, for example all MATRIX Effects.
471
 * 
472
 * @param type one of the constants defined in {@link EffectTypes}
473
 * @return Number of effects aborted.
474
 */
475
  public int abortEffects(EffectTypes type)
476
    {
477
    switch(type)
478
      {
479
      case MATRIX  : return mM.abortAll(true);
480
      case VERTEX  : return mV.abortAll(true);
481
      case FRAGMENT: return mF.abortAll(true);
482
      default      : return 0;
483
      }
484
    }
485
    
486
///////////////////////////////////////////////////////////////////////////////////////////////////
487
/**
488
 * Aborts a single Effect.
489
 * 
490
 * @param id ID of the Effect we want to abort.
491
 * @return number of Effects aborted. Always either 0 or 1.
492
 */
493
  public int abortEffect(long id)
494
    {
495
    int type = (int)(id&EffectTypes.MASK);
496

  
497
    if( type==EffectTypes.MATRIX.type   ) return mM.removeByID(id>>EffectTypes.LENGTH);
498
    if( type==EffectTypes.VERTEX.type   ) return mV.removeByID(id>>EffectTypes.LENGTH);
499
    if( type==EffectTypes.FRAGMENT.type ) return mF.removeByID(id>>EffectTypes.LENGTH);
500

  
501
    return 0;
502
    }
503

  
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505
/**
506
 * Abort all Effects of a given name, for example all rotations.
507
 * 
508
 * @param name one of the constants defined in {@link EffectNames}
509
 * @return number of Effects aborted.
510
 */
511
  public int abortEffects(EffectNames name)
512
    {
513
    switch(name.getType())
514
      {
515
      case MATRIX  : return mM.removeByType(name);
516
      case VERTEX  : return mV.removeByType(name);
517
      case FRAGMENT: return mF.removeByType(name);
518
      default      : return 0;
519
      }
520
    }
521
    
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523
/**
524
 * Print some info about a given Effect to Android's standard out. Used for debugging only.
525
 * 
526
 * @param id Effect ID we want to print info about
527
 * @return <code>true</code> if a single Effect of type effectType has been found.
528
 */
529
    
530
  public boolean printEffect(long id)
531
    {
532
    int type = (int)(id&EffectTypes.MASK);
533

  
534
    if( type==EffectTypes.MATRIX.type   )  return mM.printByID(id>>EffectTypes.LENGTH);
535
    if( type==EffectTypes.VERTEX.type   )  return mV.printByID(id>>EffectTypes.LENGTH);
536
    if( type==EffectTypes.FRAGMENT.type )  return mF.printByID(id>>EffectTypes.LENGTH);
537

  
538
    return false;
539
    }
540
   
541
///////////////////////////////////////////////////////////////////////////////////////////////////   
542
///////////////////////////////////////////////////////////////////////////////////////////////////
543
// Individual effect functions.
544
///////////////////////////////////////////////////////////////////////////////////////////////////
545
// Matrix-based effects
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547
/**
548
 * Moves the Object by a (possibly changing in time) vector.
549
 * 
550
 * @param vector 3-dimensional Data which at any given time will return a Static3D
551
 *               representing the current coordinates of the vector we want to move the Object with.
552
 * @return       ID of the effect added, or -1 if we failed to add one.
553
 */
554
  public long move(Data3D vector)
555
    {   
556
    return mM.add(EffectNames.MOVE,vector);
557
    }
558

  
559
///////////////////////////////////////////////////////////////////////////////////////////////////
560
/**
561
 * Scales the Object by (possibly changing in time) 3D scale factors.
562
 * 
563
 * @param scale 3-dimensional Data which at any given time returns a Static3D
564
 *              representing the current x- , y- and z- scale factors.
565
 * @return      ID of the effect added, or -1 if we failed to add one.
566
 */
567
  public long scale(Data3D scale)
568
    {   
569
    return mM.add(EffectNames.SCALE,scale);
570
    }
571

  
572
///////////////////////////////////////////////////////////////////////////////////////////////////
573
/**
574
 * Scales the Object by one uniform, constant factor in all 3 dimensions. Convenience function.
575
 *
576
 * @param scale The factor to scale all 3 dimensions with.
577
 * @return      ID of the effect added, or -1 if we failed to add one.
578
 */
579
  public long scale(float scale)
580
    {
581
    return mM.add(EffectNames.SCALE, new Static3D(scale,scale,scale));
582
    }
583

  
584
///////////////////////////////////////////////////////////////////////////////////////////////////
585
/**
586
 * Rotates the Object by 'angle' degrees around the center.
587
 * Static axis of rotation is given by the last parameter.
588
 *
589
 * @param angle  Angle that we want to rotate the Object to. Unit: degrees
590
 * @param axis   Axis of rotation
591
 * @param center Coordinates of the Point we are rotating around.
592
 * @return       ID of the effect added, or -1 if we failed to add one.
593
 */
594
  public long rotate(Data1D angle, Static3D axis, Data3D center )
595
    {   
596
    return mM.add(EffectNames.ROTATE, angle, axis, center);
597
    }
598

  
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600
/**
601
 * Rotates the Object by 'angle' degrees around the center.
602
 * Here both angle and axis can dynamically change.
603
 *
604
 * @param angleaxis Combined 4-tuple representing the (angle,axisX,axisY,axisZ).
605
 * @param center    Coordinates of the Point we are rotating around.
606
 * @return          ID of the effect added, or -1 if we failed to add one.
607
 */
608
  public long rotate(Data4D angleaxis, Data3D center)
609
    {
610
    return mM.add(EffectNames.ROTATE, angleaxis, center);
611
    }
612

  
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614
/**
615
 * Rotates the Object by quaternion.
616
 *
617
 * @param quaternion The quaternion describing the rotation.
618
 * @param center     Coordinates of the Point we are rotating around.
619
 * @return           ID of the effect added, or -1 if we failed to add one.
620
 */
621
  public long quaternion(Data4D quaternion, Data3D center )
622
    {
623
    return mM.add(EffectNames.QUATERNION,quaternion,center);
624
    }
625

  
626
///////////////////////////////////////////////////////////////////////////////////////////////////
627
/**
628
 * Shears the Object.
629
 *
630
 * @param shear   The 3-tuple of shear factors. The first controls level
631
 *                of shearing in the X-axis, second - Y-axis and the third -
632
 *                Z-axis. Each is the tangens of the shear angle, i.e 0 -
633
 *                no shear, 1 - shear by 45 degrees (tan(45deg)=1) etc.
634
 * @param center  Center of shearing, i.e. the point which stays unmoved.
635
 * @return        ID of the effect added, or -1 if we failed to add one.
636
 */
637
  public long shear(Data3D shear, Data3D center)
638
    {
639
    return mM.add(EffectNames.SHEAR, shear, center);
640
    }
641

  
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643
// Fragment-based effects  
644
///////////////////////////////////////////////////////////////////////////////////////////////////
645
/**
646
 * Makes a certain sub-region of the Object smoothly change all three of its RGB components.
647
 *        
648
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
649
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color.
650
 *               Valid range: <0,1>
651
 * @param color  Color to mix. (1,0,0) is RED.
652
 * @param region Region this Effect is limited to.
653
 * @param smooth If true, the level of 'blend' will smoothly fade out towards the edges of the region.
654
 * @return       ID of the effect added, or -1 if we failed to add one.
655
 */
656
  public long chroma(Data1D blend, Data3D color, Data4D region, boolean smooth)
657
    {
658
    return mF.add( smooth? EffectNames.SMOOTH_CHROMA:EffectNames.CHROMA, blend, color, region);
659
    }
660

  
661
///////////////////////////////////////////////////////////////////////////////////////////////////
662
/**
663
 * Makes the whole Object smoothly change all three of its RGB components.
664
 *
665
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
666
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color.
667
 *               Valid range: <0,1>
668
 * @param color  Color to mix. (1,0,0) is RED.
669
 * @return       ID of the effect added, or -1 if we failed to add one.
670
 */
671
  public long chroma(Data1D blend, Data3D color)
672
    {
673
    return mF.add(EffectNames.CHROMA, blend, color);
674
    }
675

  
676
///////////////////////////////////////////////////////////////////////////////////////////////////
677
/**
678
 * Makes a certain sub-region of the Object smoothly change its transparency level.
679
 *        
680
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any given
681
 *               moment: pixel.a *= alpha.
682
 *               Valid range: <0,1>
683
 * @param region Region this Effect is limited to. 
684
 * @param smooth If true, the level of 'alpha' will smoothly fade out towards the edges of the region.
685
 * @return       ID of the effect added, or -1 if we failed to add one. 
686
 */
687
  public long alpha(Data1D alpha, Data4D region, boolean smooth)
688
    {
689
    return mF.add( smooth? EffectNames.SMOOTH_ALPHA:EffectNames.ALPHA, alpha, region);
690
    }
691

  
692
///////////////////////////////////////////////////////////////////////////////////////////////////
693
/**
694
 * Makes the whole Object smoothly change its transparency level.
695
 *
696
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff