Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedObject.java @ 8c893ffc

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.opengl.GLES20;
24
import android.opengl.GLUtils;
25

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

    
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35
/**
36
 * All Objects to which Distorted Graphics effects can be applied need to be extended from here.
37
 */
38
public abstract class DistortedObject 
39
  {
40
  private static float[] mViewMatrix   = new float[16];
41
   
42
  protected EffectQueueMatrix    mM;
43
  protected EffectQueueFragment  mF;
44
  protected EffectQueueVertex    mV;
45

    
46
  protected boolean matrixCloned, vertexCloned, fragmentCloned;
47
 
48
  protected DistortedObjectGrid mGrid = null;
49
  protected long mID;
50
  protected int mSizeX, mSizeY, mSizeZ, mSize; // in screen space
51

    
52
  protected Bitmap[] mBmp= null; //
53
  int[] mTextureDataH;           // have to be shared among all the cloned Objects
54
  boolean[] mBitmapSet;          //
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

    
58
  protected abstract DistortedObject deepCopy(int flags);
59

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

    
62
  protected void initializeData(int size)
63
    {
64
    mID             = DistortedObjectList.add(this);
65
    mSize           = size;
66
    mTextureDataH   = new int[1];
67
    mTextureDataH[0]= 0;
68
    mBmp            = new Bitmap[1];
69
    mBmp[0]         = null;
70
    mBitmapSet      = new boolean[1];
71
    mBitmapSet[0]   = false;
72
      
73
    initializeEffectLists(this,0);
74
      
75
    if( Distorted.isInitialized() ) resetTexture();
76
    }
77
    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79
    
80
  protected void initializeEffectLists(DistortedObject d, int flags)
81
    {
82
    if( (flags & Distorted.CLONE_PRESHADER) != 0 )
83
      {
84
      mM = d.mM;
85
      matrixCloned = true;
86
      }
87
    else
88
      {
89
      mM = new EffectQueueMatrix(d);
90
      matrixCloned = false;
91
      }
92
    
93
    if( (flags & Distorted.CLONE_VERTEX) != 0 )
94
      {
95
      mV = d.mV;
96
      vertexCloned = true;
97
      }
98
    else
99
      {
100
      mV = new EffectQueueVertex(d);
101
      vertexCloned = false;
102
      }
103
    
104
    if( (flags & Distorted.CLONE_FRAGMENT) != 0 )
105
      {
106
      mF = d.mF;
107
      fragmentCloned = true;
108
      }
109
    else
110
      {
111
      mF = new EffectQueueFragment(d);
112
      fragmentCloned = false;
113
      }
114
    }
115
    
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117
// this will be called on startup and every time OpenGL context has been lost
118
// also call this from the constructor if the OpenGL context has been created already.
119
    
120
  void resetTexture()
121
    {
122
    if( mTextureDataH!=null )
123
      {
124
      if( mTextureDataH[0]==0 ) GLES20.glGenTextures(1, mTextureDataH, 0);
125

    
126
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
127
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
128
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
129
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
130
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
131
       
132
      if( mBmp!=null && mBmp[0]!=null)
133
        {
134
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBmp[0], 0);
135
        mBmp[0] = null;
136
        }
137
      }
138
    }
139
  
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141
   
142
  void drawPriv(long currTime, DistortedProjection dp)
143
    {
144
    GLES20.glViewport(0, 0, dp.width, dp.height);
145
      
146
    mM.compute(currTime);
147
    mM.send(mViewMatrix, dp);
148
      
149
    mV.compute(currTime);
150
    mV.postprocess();
151
    mV.send();
152
        
153
    mF.compute(currTime);
154
    mF.postprocess(mViewMatrix);
155
    mF.send();
156
       
157
    mGrid.draw();
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161
   
162
  void drawNoEffectsPriv(DistortedProjection dp)
163
    {
164
    GLES20.glViewport(0, 0, dp.width, dp.height);
165
    mM.sendNoEffects(dp);
166
    mV.sendZero();
167
    mF.sendZero();
168
    mGrid.draw();
169
    }
170
    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
   
173
  void releasePriv()
174
    {
175
    if( matrixCloned  ==false) mM.abortAll();
176
    if( vertexCloned  ==false) mV.abortAll();
177
    if( fragmentCloned==false) mF.abortAll();
178

    
179
    mBmp          = null;
180
    mGrid         = null;
181
    mM            = null;
182
    mV            = null;
183
    mF            = null;
184
    mTextureDataH = null;
185
    }
186
 
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  long getBitmapID()
190
      {
191
      return mBmp==null ? 0 : mBmp.hashCode();
192
      }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195
/**
196
 * Default empty constructor so that derived classes can call it
197
 */
198
  public DistortedObject()
199
    {
200

    
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204
/**
205
 * Copy constructor used to create a DistortedObject based on various parts of another object.
206
 * <p>
207
 * Whatever we do not clone gets created just like in the default constructor.
208
 * We only call this from the descendant's classes' constructors where we have to pay attention
209
 * to give it the appropriate type of a DistortedObject!
210
 *
211
 * @param dc    Source object to create our object from
212
 * @param flags A bitmask of values specifying what to copy.
213
 *              For example, CLONE_BITMAP | CLONE_MATRIX.
214
 */
215
  public DistortedObject(DistortedObject dc, int flags)
216
    {
217
    initializeEffectLists(dc,flags);
218

    
219
    mID = DistortedObjectList.add(this);
220

    
221
    mSizeX = dc.mSizeX;
222
    mSizeY = dc.mSizeY;
223
    mSizeZ = dc.mSizeZ;
224
    mSize  = dc.mSize;
225
    mGrid  = dc.mGrid;
226

    
227
    if( (flags & Distorted.CLONE_BITMAP) != 0 )
228
      {
229
      mTextureDataH = dc.mTextureDataH;
230
      mBmp          = dc.mBmp;
231
      mBitmapSet    = dc.mBitmapSet;
232
      }
233
    else
234
      {
235
      mTextureDataH   = new int[1];
236
      mTextureDataH[0]= 0;
237
      mBitmapSet      = new boolean[1];
238
      mBitmapSet[0]   = false;
239
      mBmp            = new Bitmap[1];
240
      mBmp[0]         = null;
241

    
242
      if( Distorted.isInitialized() ) resetTexture();
243
      }
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
/**
248
 * Draw the DistortedObject to the location specified by current Matrix effects.    
249
 *     
250
 * @param currTime current time, in milliseconds, as returned by System.currentTimeMillis().
251
 *        This gets passed on to Interpolators inside the Effects that are currently applied to the 
252
 *        Object.
253
 */
254
  public void draw(long currTime)
255
    {
256
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
257
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
258
    GLES20.glUniform1i(Distorted.mTextureUniformH, 0);
259
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
260
      
261
    drawPriv(currTime, Distorted.mProjection);
262
    }
263
 
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265
/**
266
 * Releases all resources.
267
 */
268
  public synchronized void release()
269
    {
270
    releasePriv();
271
    DistortedObjectList.remove(this);
272
    }
273

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
/**
276
 * Sets the underlying android.graphics.Bitmap object and uploads it to the GPU. 
277
 * <p>
278
 * You can only recycle() the passed Bitmap once the OpenGL context gets created (i.e. after call 
279
 * to onSurfaceCreated) because only after this point can the Library upload it to the GPU!
280
 * 
281
 * @param bmp The android.graphics.Bitmap object to apply effects to and display.
282
 */
283
   
284
  public void setBitmap(Bitmap bmp)
285
    {
286
    mBitmapSet[0] = true;
287
      
288
    if( Distorted.isInitialized() )
289
      {
290
      GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
291
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
292
      GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
293
      }
294
    else
295
      {
296
      mBmp[0] = bmp;
297
      }
298
    }
299
    
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301
/**
302
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
303
 * to one of the Effects that are currently applied to the DistortedObject.
304
 * 
305
 * @param el A class implementing the EffectListener interface that wants to get notifications.
306
 */
307
  public void addEventListener(EffectListener el)
308
    {
309
    mV.addListener(el);
310
    mF.addListener(el);
311
    mM.addListener(el);
312
    }
313

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315
/**
316
 * Removes the calling class from the list of Listeners.
317
 * 
318
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
319
 */
320
  public void removeEventListener(EffectListener el)
321
    {
322
    mV.removeListener(el);
323
    mF.removeListener(el);
324
    mM.removeListener(el);
325
    }
326
   
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328
/**
329
 * Returns the height of the DistortedObject.
330
 *    
331
 * @return height of the object, in pixels.
332
 */
333
  public int getWidth()
334
     {
335
     return mSizeX;   
336
     }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
/**
340
 * Returns the width of the DistortedObject.
341
 * 
342
 * @return width of the Object, in pixels.
343
 */
344
  public int getHeight()
345
      {
346
      return mSizeY;  
347
      }
348
    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350
/**
351
 * Returns the depth of the DistortedObject.
352
 * 
353
 * @return depth of the Object, in pixels.
354
 */
355
  public int getDepth()
356
      {
357
      return mSizeZ;  
358
      }
359
        
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361
/**
362
 * Returns unique ID of this instance.
363
 * 
364
 * @return ID of the object.
365
 */
366
  public long getID()
367
      {
368
      return mID;  
369
      }
370
    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372
/**
373
 * Aborts all Effects.
374
 * @return Number of effects aborted.
375
 */
376
  public int abortAllEffects()
377
      {
378
      return mM.abortAll() + mV.abortAll() + mF.abortAll();
379
      }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382
/**
383
 * Aborts all Effects of a given type, for example all MATRIX Effects.
384
 * 
385
 * @param type one of the constants defined in {@link EffectTypes}
386
 * @return Number of effects aborted.
387
 */
388
  public int abortEffects(EffectTypes type)
389
    {
390
    switch(type)
391
      {
392
      case MATRIX  : return mM.abortAll();
393
      case VERTEX  : return mV.abortAll();
394
      case FRAGMENT: return mF.abortAll();
395
      default      : return 0;
396
      }
397
    }
398
    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400
/**
401
 * Aborts a single Effect.
402
 * 
403
 * @param id ID of the Effect we want to abort.
404
 * @return number of Effects aborted. Always either 0 or 1.
405
 */
406
  public int abortEffect(long id)
407
    {
408
    int type = (int)(id&EffectTypes.MASK);
409

    
410
    if( type==EffectTypes.MATRIX.type   ) return mM.removeByID(id>>EffectTypes.LENGTH);
411
    if( type==EffectTypes.VERTEX.type   ) return mV.removeByID(id>>EffectTypes.LENGTH);
412
    if( type==EffectTypes.FRAGMENT.type ) return mF.removeByID(id>>EffectTypes.LENGTH);
413

    
414
    return 0;
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418
/**
419
 * Abort all Effects of a given type, for example all rotations.
420
 * 
421
 * @param name one of the constants defined in {@link EffectNames}
422
 * @return number of Effects aborted.
423
 */
424
  public int abortEffects(EffectNames name)
425
    {
426
    switch(name.getType())
427
      {
428
      case MATRIX  : return mM.removeByType(name);
429
      case VERTEX  : return mV.removeByType(name);
430
      case FRAGMENT: return mF.removeByType(name);
431
      default      : return 0;
432
      }
433
    }
434
    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436
/**
437
 * Print some info about a given Effect to Android's standard out. Used for debugging only.
438
 * 
439
 * @param id Effect ID we want to print info about
440
 * @return <code>true</code> if a single Effect of type effectType has been found.
441
 */
442
    
443
  public boolean printEffect(long id)
444
    {
445
    int type = (int)(id&EffectTypes.MASK);
446

    
447
    if( type==EffectTypes.MATRIX.type   )  return mM.printByID(id>>EffectTypes.LENGTH);
448
    if( type==EffectTypes.VERTEX.type   )  return mV.printByID(id>>EffectTypes.LENGTH);
449
    if( type==EffectTypes.FRAGMENT.type )  return mF.printByID(id>>EffectTypes.LENGTH);
450

    
451
    return false;
452
    }
453
   
454
///////////////////////////////////////////////////////////////////////////////////////////////////   
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456
// Individual effect functions.
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458
// Matrix-based effects
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460
/**
461
 * Moves the Object by a vector that changes in time as interpolated by the Dynamic.
462
 * 
463
 * @param vector 3-dimensional Data which at any given time will return a Static3D
464
 *               representing the current coordinates of the vector we want to move the Object with.
465
 * @return       ID of the effect added, or -1 if we failed to add one.
466
 */
467
  public long move(Data3D vector)
468
    {   
469
    return mM.add(EffectNames.MOVE,vector);
470
    }
471

    
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473
/**
474
 * Scales the Object by factors that change in time as returned by the Dynamic.
475
 * 
476
 * @param scale 3-dimensional Dynamic which at any given time returns a Static3D
477
 *              representing the current x- , y- and z- scale factors.
478
 * @return      ID of the effect added, or -1 if we failed to add one.
479
 */
480
  public long scale(Data3D scale)
481
    {   
482
    return mM.add(EffectNames.SCALE,scale);
483
    }
484

    
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486
/**
487
 * Scales the Object by one uniform factor in all 3 dimensions. Convenience function.
488
 *
489
 * @param scale The factor to scale all 3 dimensions with.
490
 * @return      ID of the effect added, or -1 if we failed to add one.
491
 */
492
  public long scale(float scale)
493
    {
494
    return mM.add(EffectNames.SCALE, new Static3D(scale,scale,scale));
495
    }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498
/**
499
 * Rotates the Object by 'angle' degrees around the center.
500
 * Static axis of rotation is given by the last parameter.
501
 *
502
 * @param center Coordinates of the Point we are rotating around.
503
 * @param angle  Angle that we want to rotate the Object to. Unit: degrees
504
 * @param axis   Axis of rotation
505
 * @return       ID of the effect added, or -1 if we failed to add one.
506
 */
507
  public long rotate(Data3D center, Data1D angle, Static3D axis)
508
    {   
509
    return mM.add(EffectNames.ROTATE, center, angle, axis);
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513
/**
514
 * Rotates the Object by 'angle' degrees around the center.
515
 * Here both angle and axis can dynamically change.
516
 *
517
 * @param center    Coordinates of the Point we are rotating around.
518
 * @param angleaxis Combined 4-tuple representing the (angle,axisX,axisY,axisZ).
519
 * @return          ID of the effect added, or -1 if we failed to add one.
520
 */
521
  public long rotate(Data3D center, Data4D angleaxis)
522
    {
523
    return mM.add(EffectNames.ROTATE, center, angleaxis);
524
    }
525

    
526
///////////////////////////////////////////////////////////////////////////////////////////////////
527
/**
528
 * Rotates the Object by quaternion.
529
 *   
530
 * @param center     Coordinates of the Point we are rotating around.
531
 * @param quaternion The quaternion describing the rotation.
532
 * @return           ID of the effect added, or -1 if we failed to add one.
533
 */
534
  public long quaternion(Data3D center, Data4D quaternion)
535
    {
536
    return mM.add(EffectNames.QUATERNION,center,quaternion);
537
    }
538

    
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540
/**
541
 * Shears the Object.
542
 *
543
 * @param center  Center of shearing, i.e. the point which stays unmoved.
544
 * @param shear   The 3-tuple of shear factors.
545
 * @return        ID of the effect added, or -1 if we failed to add one.
546
 */
547
  public long shear(Data3D center, Data3D shear)
548
    {
549
    return mM.add(EffectNames.SHEAR, center, shear);
550
    }
551

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553
// Fragment-based effects  
554
///////////////////////////////////////////////////////////////////////////////////////////////////
555
/**
556
 * Creates macroblocks at and around point defined by the Region.
557
 * 
558
 * @param size   1-dimensional Dynamic which, at any given time, returns the size of the macroblocks.
559
 * @param region Region this Effect is limited to.
560
 * @return       ID of the effect added, or -1 if we failed to add one.
561
 */
562
  public long macroblock(Data1D size, Data4D region)
563
    {
564
    return mF.add(EffectNames.MACROBLOCK, size, region);
565
    }
566

    
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568
/**
569
 * Creates macroblocks on the whole Object.
570
 *
571
 * @param size   1-dimensional Data which, at any given time, returns the size of the macroblocks.
572
 * @return       ID of the effect added, or -1 if we failed to add one.
573
 */
574
  public long macroblock(Data1D size)
575
    {
576
    return mF.add(EffectNames.MACROBLOCK, size);
577
    }
578

    
579
///////////////////////////////////////////////////////////////////////////////////////////////////
580
/**
581
 * Makes a certain sub-region of the Object smoothly change all three of its RGB components.
582
 *        
583
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
584
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color
585
 * @param color  Color to mix. (1,0,0) is RED.
586
 * @param region Region this Effect is limited to.
587
 * @param smooth If true, the level of 'blend' will smoothly fade out towards the edges of the region.
588
 * @return       ID of the effect added, or -1 if we failed to add one.
589
 */
590
  public long chroma(Data1D blend, Data3D color, Data4D region, boolean smooth)
591
    {
592
    return mF.add( smooth? EffectNames.SMOOTH_CHROMA:EffectNames.CHROMA, blend, color, region);
593
    }
594

    
595
///////////////////////////////////////////////////////////////////////////////////////////////////
596
/**
597
 * Makes the whole Object smoothly change all three of its RGB components.
598
 *
599
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
600
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color
601
 * @param color  Color to mix. (1,0,0) is RED.
602
 * @return       ID of the effect added, or -1 if we failed to add one.
603
 */
604
  public long chroma(Data1D blend, Data3D color)
605
    {
606
    return mF.add(EffectNames.CHROMA, blend, color);
607
    }
608

    
609
///////////////////////////////////////////////////////////////////////////////////////////////////
610
/**
611
 * Makes a certain sub-region of the Object smoothly change its transparency level.
612
 *        
613
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any given
614
 *               moment.
615
 * @param region Region this Effect is limited to. 
616
 * @param smooth If true, the level of 'alpha' will smoothly fade out towards the edges of the region.
617
 * @return       ID of the effect added, or -1 if we failed to add one. 
618
 */
619
  public long alpha(Data1D alpha, Data4D region, boolean smooth)
620
    {
621
    return mF.add( smooth? EffectNames.SMOOTH_ALPHA:EffectNames.ALPHA, alpha, region);
622
    }
623

    
624
///////////////////////////////////////////////////////////////////////////////////////////////////
625
/**
626
 * Makes the whole Object smoothly change its transparency level.
627
 *
628
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any
629
 *               given moment.
630
 * @return       ID of the effect added, or -1 if we failed to add one.
631
 */
632
  public long alpha(Data1D alpha)
633
    {
634
    return mF.add(EffectNames.ALPHA, alpha);
635
    }
636

    
637
///////////////////////////////////////////////////////////////////////////////////////////////////
638
/**
639
 * Makes a certain sub-region of the Object smoothly change its brightness level.
640
 *        
641
 * @param brightness 1-dimensional Data that returns the level of brightness we want to have
642
 *                   at any given moment.
643
 * @param region     Region this Effect is limited to.
644
 * @param smooth     If true, the level of 'brightness' will smoothly fade out towards the edges of the region.
645
 * @return           ID of the effect added, or -1 if we failed to add one.
646
 */
647
  public long brightness(Data1D brightness, Data4D region, boolean smooth)
648
    {
649
    return mF.add( smooth ? EffectNames.SMOOTH_BRIGHTNESS: EffectNames.BRIGHTNESS, brightness, region);
650
    }
651

    
652
///////////////////////////////////////////////////////////////////////////////////////////////////
653
/**
654
 * Makes the whole Object smoothly change its brightness level.
655
 *
656
 * @param brightness 1-dimensional Data that returns the level of brightness we want to have
657
 *                   at any given moment.
658
 * @return           ID of the effect added, or -1 if we failed to add one.
659
 */
660
  public long brightness(Data1D brightness)
661
    {
662
    return mF.add(EffectNames.BRIGHTNESS, brightness);
663
    }
664

    
665
///////////////////////////////////////////////////////////////////////////////////////////////////
666
/**
667
 * Makes a certain sub-region of the Object smoothly change its contrast level.
668
 *        
669
 * @param contrast 1-dimensional Data that returns the level of contrast we want to have
670
 *                 at any given moment.
671
 * @param region   Region this Effect is limited to.
672
 * @param smooth   If true, the level of 'contrast' will smoothly fade out towards the edges of the region.
673
 * @return         ID of the effect added, or -1 if we failed to add one.
674
 */
675
  public long contrast(Data1D contrast, Data4D region, boolean smooth)
676
    {
677
    return mF.add( smooth ? EffectNames.SMOOTH_CONTRAST:EffectNames.CONTRAST, contrast, region);
678
    }
679

    
680
///////////////////////////////////////////////////////////////////////////////////////////////////
681
/**
682
 * Makes the whole Object smoothly change its contrast level.
683
 *
684
 * @param contrast 1-dimensional Data that returns the level of contrast we want to have
685
 *                 at any given moment.
686
 * @return         ID of the effect added, or -1 if we failed to add one.
687
 */
688
  public long contrast(Data1D contrast)
689
    {
690
    return mF.add(EffectNames.CONTRAST, contrast);
691
    }
692

    
693
///////////////////////////////////////////////////////////////////////////////////////////////////
694
/**
695
 * Makes a certain sub-region of the Object smoothly change its saturation level.
696
 *        
697
 * @param saturation 1-dimensional Data that returns the level of saturation we want to have
698
 *                   at any given moment.
699
 * @param region     Region this Effect is limited to.
700
 * @param smooth     If true, the level of 'saturation' will smoothly fade out towards the edges of the region.
701
 * @return           ID of the effect added, or -1 if we failed to add one.
702
 */
703
  public long saturation(Data1D saturation, Data4D region, boolean smooth)
704
    {
705
    return mF.add( smooth ? EffectNames.SMOOTH_SATURATION:EffectNames.SATURATION, saturation, region);
706
    }
707

    
708
///////////////////////////////////////////////////////////////////////////////////////////////////
709
/**
710
 * Makes the whole Object smoothly change its saturation level.
711
 *
712
 * @param saturation 1-dimensional Data that returns the level of saturation we want to have
713
 *                   at any given moment.
714
 * @return           ID of the effect added, or -1 if we failed to add one.
715
 */
716
  public long saturation(Data1D saturation)
717
    {
718
    return mF.add(EffectNames.SATURATION, saturation);
719
    }
720

    
721
///////////////////////////////////////////////////////////////////////////////////////////////////
722
// Vertex-based effects  
723
///////////////////////////////////////////////////////////////////////////////////////////////////
724
/**
725
 * Distort a (possibly changing in time) part of the Object by a (possibly changing in time) vector of force.
726
 *
727
 * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
728
 *               currently being dragged with.
729
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
730
 * @param region Region that masks the Effect.
731
 * @return       ID of the effect added, or -1 if we failed to add one.
732
 */
733
  public long distort(Data3D vector, Data2D center, Data4D region)
734
    {  
735
    return mV.add(EffectNames.DISTORT, vector, center, region);
736
    }
737

    
738
///////////////////////////////////////////////////////////////////////////////////////////////////
739
/**
740
 * Distort the whole Object by a (possibly changing in time) vector of force.
741
 *
742
 * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
743
 *               currently being dragged with.
744
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
745
 * @return       ID of the effect added, or -1 if we failed to add one.
746
 */
747
  public long distort(Data3D vector, Data2D center)
748
    {
749
    return mV.add(EffectNames.DISTORT, vector, center);
750
    }
751

    
752
///////////////////////////////////////////////////////////////////////////////////////////////////
753
/**
754
 * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
755
 * a (possibly changing in time) point on the Object.
756
 *     
757
 * @param vector Vector of force that deforms the shape of the whole Object.
758
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
759
 * @return       ID of the effect added, or -1 if we failed to add one.
760
 */
761
  public long deform(Data3D vector, Data2D center)
762
    {  
763
    return mV.add(EffectNames.DEFORM, vector, center);
764
    }
765

    
766
///////////////////////////////////////////////////////////////////////////////////////////////////  
767
/**
768
 * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
769
 * away from the center (degree<=1)
770
 *
771
 * @param sink   The current degree of the Effect.
772
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
773
 * @param region Region that masks the Effect.
774
 * @return       ID of the effect added, or -1 if we failed to add one.
775
 */
776
  public long sink(Data1D sink, Data2D center, Data4D region)
777
    {
778
    return mV.add(EffectNames.SINK, sink, center, region);
779
    }
780

    
781
///////////////////////////////////////////////////////////////////////////////////////////////////
782
/**
783
 * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
784
 * away from the center (degree<=1)
785
 *
786
 * @param sink   The current degree of the Effect.
787
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
788
 * @return       ID of the effect added, or -1 if we failed to add one.
789
 */
790
  public long sink(Data1D sink, Data2D center)
791
    {
792
    return mV.add(EffectNames.SINK, sink, center);
793
    }
794

    
795
///////////////////////////////////////////////////////////////////////////////////////////////////  
796
/**
797
 * Rotate part of the Object around the Center of the Effect by a certain angle.
798
 *
799
 * @param swirl  The degree of Swirl. Positive values swirl clockwise.
800
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
801
 * @param region Region that masks the Effect.
802
 * @return       ID of the effect added, or -1 if we failed to add one.
803
 */
804
  public long swirl(Data1D swirl, Data2D center, Data4D region)
805
    {    
806
    return mV.add(EffectNames.SWIRL, swirl, center, region);
807
    }
808

    
809
///////////////////////////////////////////////////////////////////////////////////////////////////
810
/**
811
 * Rotate the whole Object around the Center of the Effect by a certain angle.
812
 *
813
 * @param swirl  The degree of Swirl. Positive values swirl clockwise.
814
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
815
 * @return       ID of the effect added, or -1 if we failed to add one.
816
 */
817
  public long swirl(Data1D swirl, Data2D center)
818
    {
819
    return mV.add(EffectNames.SWIRL, swirl, center);
820
    }
821
  }
(7-7/17)