Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedObject.java @ 2fce34f4

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.Data3D;
29
import org.distorted.library.type.Data4D;
30
import org.distorted.library.type.Dynamic;
31
import org.distorted.library.type.Dynamic1D;
32
import org.distorted.library.type.Dynamic2D;
33
import org.distorted.library.type.Dynamic3D;
34
import org.distorted.library.type.Dynamic4D;
35
import org.distorted.library.type.Static1D;
36
import org.distorted.library.type.Static2D;
37
import org.distorted.library.type.Static3D;
38
import org.distorted.library.type.Static4D;
39
import org.distorted.library.type.DynamicQuat;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42
/**
43
 * All Objects to which Distorted Graphics effects can be applied need to be extended from here.
44
 */
45
public abstract class DistortedObject 
46
{
47
    private static final Static2D mZero2D = new Static2D(0,0);
48
    private static final Static3D mZero3D = new Static3D(0,0,0);
49

    
50
    private static float[] mViewMatrix   = new float[16];
51
   
52
    protected EffectQueueMatrix    mM;
53
    protected EffectQueueFragment  mF;
54
    protected EffectQueueVertex    mV;
55

    
56
    protected boolean matrixCloned, vertexCloned, fragmentCloned;
57
 
58
    protected DistortedObjectGrid mGrid = null;
59
    protected long mID;
60
    protected int mSizeX, mSizeY, mSizeZ, mSize; // in screen space
61

    
62
    protected Bitmap[] mBmp= null; // 
63
    int[] mTextureDataH;           // have to be shared among all the cloned Objects
64
    boolean[] mBitmapSet;          // 
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
    protected abstract DistortedObject deepCopy(int flags);
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

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

    
136
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);       
137
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
138
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
139
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
140
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
141
       
142
        if( mBmp!=null && mBmp[0]!=null)
143
          {
144
          GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBmp[0], 0);
145
          mBmp[0] = null;
146
          }
147
        }
148
      }
149
  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151
   
152
    void drawPriv(long currTime, DistortedProjection dp)
153
      {
154
      GLES20.glViewport(0, 0, dp.width, dp.height); 
155
      
156
      mM.compute(currTime);
157
      mM.send(mViewMatrix, dp);
158
      
159
      mV.compute(currTime);
160
      mV.postprocess();
161
      mV.send();
162
        
163
      mF.compute(currTime);
164
      mF.postprocess(mViewMatrix);
165
      mF.send();
166
       
167
      mGrid.draw();
168
      }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171
   
172
    void drawNoEffectsPriv(DistortedProjection dp)
173
      {
174
      GLES20.glViewport(0, 0, dp.width, dp.height);
175
      mM.sendNoEffects(dp);
176
      mV.sendZero();
177
      mF.sendZero();
178
      mGrid.draw();
179
      }
180
    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182
   
183
    void releasePriv()
184
      {
185
      if( matrixCloned  ==false) mM.abortAll();
186
      if( vertexCloned  ==false) mV.abortAll();
187
      if( fragmentCloned==false) mF.abortAll();
188

    
189
      mBmp          = null;
190
      mGrid         = null;
191
      mM            = null;
192
      mV            = null;
193
      mF            = null;
194
      mTextureDataH = null;
195
      }
196
 
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
    long getBitmapID()
200
      {
201
      return mBmp==null ? 0 : mBmp.hashCode();
202
      }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  /**
207
   * Default empty constructor so that derived classes can call it
208
   */
209
    public DistortedObject()
210
      {
211

    
212
      }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
  /**
216
   * Copy constructor used to create a DistortedObject based on various parts of another object.
217
   * <p>
218
   * Whatever we do not clone gets created just like in the default constructor.
219
   * We only call this from the descendant's classes' constructors where we have to pay attention
220
   * to give it the appropriate type of a DistortedObject!
221
   *
222
   * @param dc    Source object to create our object from
223
   * @param flags A bitmask of values specifying what to copy.
224
   *              For example, CLONE_BITMAP | CLONE_MATRIX.
225
   */
226
    public DistortedObject(DistortedObject dc, int flags)
227
      {
228
      initializeEffectLists(dc,flags);
229

    
230
      mID = DistortedObjectList.add(this);
231

    
232
      mSizeX = dc.mSizeX;
233
      mSizeY = dc.mSizeY;
234
      mSizeZ = dc.mSizeZ;
235
      mSize  = dc.mSize;
236
      mGrid  = dc.mGrid;
237

    
238
      if( (flags & Distorted.CLONE_BITMAP) != 0 )
239
        {
240
        mTextureDataH = dc.mTextureDataH;
241
        mBmp          = dc.mBmp;
242
        mBitmapSet    = dc.mBitmapSet;
243
        }
244
      else
245
        {
246
        mTextureDataH   = new int[1];
247
        mTextureDataH[0]= 0;
248
        mBitmapSet      = new boolean[1];
249
        mBitmapSet[0]   = false;
250
        mBmp            = new Bitmap[1];
251
        mBmp[0]         = null;
252

    
253
        if( Distorted.isInitialized() ) resetTexture();
254
        }
255
      }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
/**
259
 * Draw the DistortedObject to the location specified by current Matrix effects.    
260
 *     
261
 * @param currTime current time, in milliseconds, as returned by System.currentTimeMillis().
262
 *        This gets passed on to Interpolators inside the Effects that are currently applied to the 
263
 *        Object.
264
 */
265
   public void draw(long currTime)
266
     {
267
     GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
268
     GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
269
     GLES20.glUniform1i(Distorted.mTextureUniformH, 0);  
270
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]); 
271
      
272
     drawPriv(currTime, Distorted.mProjection);
273
     }
274
 
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276
/**
277
 * Releases all resources.
278
 */
279
   public synchronized void release()
280
     {
281
     releasePriv();  
282
     DistortedObjectList.remove(this);
283
     }
284

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

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326
/**
327
 * Removes the calling class from the list of Listeners.
328
 * 
329
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
330
 */
331
   public void removeEventListener(EffectListener el)
332
     {
333
     mV.removeListener(el);
334
     mF.removeListener(el);
335
     mM.removeListener(el);
336
     }
337
   
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
/**
340
 * Returns the height of the DistortedObject.
341
 *    
342
 * @return height of the object, in pixels.
343
 */
344
   public int getWidth()
345
     {
346
     return mSizeX;   
347
     }
348

    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350
/**
351
 * Returns the width of the DistortedObject.
352
 * 
353
 * @return width of the Object, in pixels.
354
 */
355
    public int getHeight()
356
      {
357
      return mSizeY;  
358
      }
359
    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361
/**
362
 * Returns the depth of the DistortedObject.
363
 * 
364
 * @return depth of the Object, in pixels.
365
 */
366
    public int getDepth()
367
      {
368
      return mSizeZ;  
369
      }
370
        
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372
/**
373
 * Returns unique ID of this instance.
374
 * 
375
 * @return ID of the object.
376
 */
377
    public long getID()
378
      {
379
      return mID;  
380
      }
381
    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
/**
384
 * Aborts all Effects.
385
 * @return Number of effects aborted.
386
 */
387
    public int abortAllEffects()
388
      {
389
      return mM.abortAll() + mV.abortAll() + mF.abortAll();
390
      }
391

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393
/**
394
 * Aborts all Effects of a given type, for example all MATRIX Effects.
395
 * 
396
 * @param type one of the constants defined in {@link EffectTypes}
397
 * @return Number of effects aborted.
398
 */
399
    public int abortEffects(EffectTypes type)
400
      {
401
      switch(type)
402
        {
403
        case MATRIX  : return mM.abortAll();
404
        case VERTEX  : return mV.abortAll();
405
        case FRAGMENT: return mF.abortAll();
406
        default      : return 0;
407
        }
408
      }
409
    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411
/**
412
 * Aborts a single Effect.
413
 * 
414
 * @param id ID of the Effect we want to abort.
415
 * @return number of Effects aborted. Always either 0 or 1.
416
 */
417
    public int abortEffect(long id)
418
      {
419
      int type = (int)(id&EffectTypes.MASK);
420

    
421
      if( type==EffectTypes.MATRIX.type   ) return mM.removeByID(id>>EffectTypes.LENGTH);
422
      if( type==EffectTypes.VERTEX.type   ) return mV.removeByID(id>>EffectTypes.LENGTH);
423
      if( type==EffectTypes.FRAGMENT.type ) return mF.removeByID(id>>EffectTypes.LENGTH);
424

    
425
      return 0;
426
      }
427

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

    
458
      if( type==EffectTypes.MATRIX.type   )  return mM.printByID(id>>EffectTypes.LENGTH);
459
      if( type==EffectTypes.VERTEX.type   )  return mV.printByID(id>>EffectTypes.LENGTH);
460
      if( type==EffectTypes.FRAGMENT.type )  return mF.printByID(id>>EffectTypes.LENGTH);
461

    
462
      return false;
463
      }
464
   
465
///////////////////////////////////////////////////////////////////////////////////////////////////   
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467
// Individual effect functions.
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469
// Matrix-based effects
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471
/**
472
 * Moves the Object by a vector that changes in time as interpolated by the Dynamic.
473
 * 
474
 * @param vector 3-dimensional Data which at any given time will return a Static3D
475
 *               representing the current coordinates of the vector we want to move the Object with.
476
 * @return       ID of the effect added, or -1 if we failed to add one.
477
 */
478
  public long move(Data3D vector)
479
    {   
480
    return mM.add(EffectNames.MOVE,vector);
481
    }
482

    
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484
/**
485
 * Scales the Object by factors that change in time as returned by the Dynamic.
486
 * 
487
 * @param scale 3-dimensional Dynamic which at any given time returns a Static3D
488
 *              representing the current x- , y- and z- scale factors.
489
 * @return      ID of the effect added, or -1 if we failed to add one.
490
 */
491
  public long scale(Data3D scale)
492
    {   
493
    return mM.add(EffectNames.SCALE,scale);
494
    }
495

    
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497
/**
498
 * Scales the Object by one uniform factor in all 3 dimensions. Convenience function.
499
 *
500
 * @param scale The factor to scale all 3 dimensions with.
501
 * @return      ID of the effect added, or -1 if we failed to add one.
502
 */
503
public long scale(float scale)
504
  {
505
  return mM.add(EffectNames.SCALE, new Static3D(scale,scale,scale));
506
  }
507

    
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509
/**
510
 * Rotates the Object by 'angle' degrees around the center.
511
 * Static axis of rotation is given by the last parameter.
512
 *
513
 * @param center Coordinates of the Point we are rotating around.
514
 * @param angle  Angle that we want to rotate the Object to. Unit: degrees
515
 * @param axis   Axis of rotation
516
 * @return       ID of the effect added, or -1 if we failed to add one.
517
 */
518
  public long rotate(Data3D center, Data1D angle, Static3D axis)
519
    {   
520
    return mM.add(EffectNames.ROTATE, center, angle, axis);
521
    }
522

    
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524
/**
525
 * Rotates the Object by 'angle' degrees around the center.
526
 * Here both angle and axis can dynamically change.
527
 *
528
 * @param center    Coordinates of the Point we are rotating around.
529
 * @param angleaxis Combined 4-tuple representing the (angle,axisX,axisY,axisZ).
530
 * @return          ID of the effect added, or -1 if we failed to add one.
531
 */
532
  public long rotate(Data3D center, Data4D angleaxis)
533
    {
534
    return mM.add(EffectNames.ROTATE, center, angleaxis);
535
    }
536

    
537
///////////////////////////////////////////////////////////////////////////////////////////////////
538
/**
539
 * Rotates the Object by quaternion.
540
 *   
541
 * @param center     Coordinates of the Point we are rotating around.
542
 * @param quaternion The quaternion describing the rotation.
543
 * @return           ID of the effect added, or -1 if we failed to add one.
544
 */
545
  public long quaternion(Data3D center, Data4D quaternion)
546
    {
547
    return mM.add(EffectNames.QUATERNION,center,quaternion);
548
    }
549

    
550
///////////////////////////////////////////////////////////////////////////////////////////////////
551
/**
552
 * Shears the Object.
553
 *
554
 * @param center  Center of shearing, i.e. the point which stays unmoved.
555
 * @param shear   The 3-tuple of shear factors.
556
 * @return        ID of the effect added, or -1 if we failed to add one.
557
 */
558
  public long shear(Data3D center, Data3D shear)
559
    {
560
    return mM.add(EffectNames.SHEAR, center, shear);
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564
// Fragment-based effects  
565
///////////////////////////////////////////////////////////////////////////////////////////////////
566
/**
567
 * Creates macroblocks at and around point defined by the Region.
568
 * 
569
 * @param size   1-dimensional Dynamic which, at any given time, returns the size of the macroblocks.
570
 * @param region Region this Effect is limited to.
571
 * @return       ID of the effect added, or -1 if we failed to add one.
572
 */
573
  public long macroblock(Data1D size, Data4D region)
574
    {
575
    return mF.add(EffectNames.MACROBLOCK, size, region);
576
    }
577

    
578
///////////////////////////////////////////////////////////////////////////////////////////////////
579
/**
580
 * Creates macroblocks on the whole Object.
581
 *
582
 * @param size   1-dimensional Data which, at any given time, returns the size of the macroblocks.
583
 * @return       ID of the effect added, or -1 if we failed to add one.
584
 */
585
  public long macroblock(Data1D size)
586
    {
587
    return mF.add(EffectNames.MACROBLOCK, size);
588
    }
589

    
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591
/**
592
 * Makes a certain sub-region of the Object smoothly change all three of its RGB components.
593
 *        
594
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
595
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color
596
 * @param color  Color to mix. (1,0,0) is RED.
597
 * @param region Region this Effect is limited to.
598
 * @param smooth If true, the level of 'blend' will smoothly fade out towards the edges of the region.
599
 * @return       ID of the effect added, or -1 if we failed to add one.
600
 */
601
  public long chroma(Data1D blend, Static3D color, Data4D region, boolean smooth)
602
    {
603
    return mF.add( smooth? EffectNames.SMOOTH_CHROMA:EffectNames.CHROMA, blend, color, region);
604
    }
605

    
606
///////////////////////////////////////////////////////////////////////////////////////////////////
607
/**
608
 * Makes the whole Object smoothly change all three of its RGB components.
609
 *
610
 * @param blend  1-dimensional Data that returns the level of blend a given pixel will be
611
 *               mixed with the next parameter 'color': pixel = (1-level)*pixel + level*color
612
 * @param color  Color to mix. (1,0,0) is RED.
613
 * @return       ID of the effect added, or -1 if we failed to add one.
614
 */
615
  public long chroma(Data1D blend, Static3D color)
616
    {
617
    return mF.add(EffectNames.CHROMA, blend, color);
618
    }
619

    
620
///////////////////////////////////////////////////////////////////////////////////////////////////  
621
/**
622
 * Makes a certain sub-region of the Object smoothly change all three of its RGB components.
623
 *        
624
 * @param blendcolor  4-dimensional Data returning the 4-tuple (blend,R,G,B).
625
 *                    Level of blend a given pixel will be mixed with the next parameter 'color':
626
 *                    pixel = (1-t)*pixel + t*color
627
 * @param region Region this Effect is limited to.
628
 * @param smooth If true, the level of 'blend' will smoothly fade out towards the edges of the region.
629
 * @return       ID of the effect added, or -1 if we failed to add one.
630
 */
631
  public long chroma(Data4D blendcolor, Data4D region, boolean smooth )
632
    {
633
    return mF.add( smooth? EffectNames.SMOOTH_CHROMA:EffectNames.CHROMA, blendcolor, region );
634
    }
635

    
636
///////////////////////////////////////////////////////////////////////////////////////////////////
637
/**
638
 * Makes the whole Object smoothly change all three of its RGB components.
639
 *
640
 * @param blendcolor  4-dimensional Data returning the 4-tuple (blend,R,G,B).
641
 *                    Level of blend a given pixel will be mixed with the next parameter 'color':
642
 *                    pixel = (1-t)*pixel + t*color
643
 * @return       ID of the effect added, or -1 if we failed to add one. 
644
 */
645
  public long chroma(Data4D blendcolor)
646
    {
647
    return mF.add(EffectNames.CHROMA, blendcolor);
648
    }
649

    
650
///////////////////////////////////////////////////////////////////////////////////////////////////
651
/**
652
 * Makes a certain sub-region of the Object smoothly change its transparency level.
653
 *        
654
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any given
655
 *               moment.
656
 * @param region Region this Effect is limited to. 
657
 * @param smooth If true, the level of 'alpha' will smoothly fade out towards the edges of the region.
658
 * @return       ID of the effect added, or -1 if we failed to add one. 
659
 */
660
  public long alpha(Data1D alpha, Data4D region, boolean smooth)
661
    {
662
    return mF.add( smooth? EffectNames.SMOOTH_ALPHA:EffectNames.ALPHA, alpha, region);
663
    }
664

    
665
///////////////////////////////////////////////////////////////////////////////////////////////////
666
/**
667
 * Makes the whole Object smoothly change its transparency level.
668
 *
669
 * @param alpha  1-dimensional Data that returns the level of transparency we want to have at any
670
 *               given moment.
671
 * @return       ID of the effect added, or -1 if we failed to add one.
672
 */
673
  public long alpha(Data1D alpha)
674
    {
675
    return mF.add(EffectNames.ALPHA, alpha);
676
    }
677

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

    
693
///////////////////////////////////////////////////////////////////////////////////////////////////
694
/**
695
 * Makes the whole Object smoothly change its brightness level.
696
 *
697
 * @param brightness 1-dimensional Data that returns the level of brightness we want to have
698
 *                   at any given moment.
699
 * @return           ID of the effect added, or -1 if we failed to add one.
700
 */
701
  public long brightness(Data1D brightness)
702
    {
703
    return mF.add(EffectNames.BRIGHTNESS, brightness);
704
    }
705

    
706
///////////////////////////////////////////////////////////////////////////////////////////////////
707
/**
708
 * Makes a certain sub-region of the Object smoothly change its contrast level.
709
 *        
710
 * @param contrast 1-dimensional Data that returns the level of contrast we want to have
711
 *                 at any given moment.
712
 * @param region   Region this Effect is limited to.
713
 * @param smooth   If true, the level of 'contrast' will smoothly fade out towards the edges of the region.
714
 * @return         ID of the effect added, or -1 if we failed to add one.
715
 */
716
  public long contrast(Data1D contrast, Data4D region, boolean smooth)
717
    {
718
    return mF.add( smooth ? EffectNames.SMOOTH_CONTRAST:EffectNames.CONTRAST, contrast, region);
719
    }
720

    
721
///////////////////////////////////////////////////////////////////////////////////////////////////
722
/**
723
 * Makes the whole Object smoothly change its contrast level.
724
 *
725
 * @param contrast 1-dimensional Data that returns the level of contrast we want to have
726
 *                 at any given moment.
727
 * @return         ID of the effect added, or -1 if we failed to add one.
728
 */
729
  public long contrast(Data1D contrast)
730
    {
731
    return mF.add(EffectNames.CONTRAST, contrast);
732
    }
733

    
734
///////////////////////////////////////////////////////////////////////////////////////////////////
735
/**
736
 * Makes a certain sub-region of the Object smoothly change its saturation level.
737
 *        
738
 * @param saturation 1-dimensional Data that returns the level of saturation we want to have
739
 *                   at any given moment.
740
 * @param region     Region this Effect is limited to.
741
 * @param smooth     If true, the level of 'saturation' will smoothly fade out towards the edges of the region.
742
 * @return           ID of the effect added, or -1 if we failed to add one.
743
 */
744
  public long saturation(Data1D saturation, Data4D region, boolean smooth)
745
    {
746
    return mF.add( smooth ? EffectNames.SMOOTH_SATURATION:EffectNames.SATURATION, saturation, region);
747
    }
748

    
749
///////////////////////////////////////////////////////////////////////////////////////////////////
750
/**
751
 * Makes the whole Object smoothly change its saturation level.
752
 *
753
 * @param saturation 1-dimensional Data that returns the level of saturation we want to have
754
 *                   at any given moment.
755
 * @return           ID of the effect added, or -1 if we failed to add one.
756
 */
757
  public long saturation(Data1D saturation)
758
    {
759
    return mF.add(EffectNames.SATURATION, saturation);
760
    }
761

    
762
///////////////////////////////////////////////////////////////////////////////////////////////////
763
// Vertex-based effects  
764
///////////////////////////////////////////////////////////////////////////////////////////////////
765
// DISTORT
766
/**
767
 * Distort a (possibly changing in time) part of the Object by a (possibly changing in time) vector of force.
768
 * 
769
 * @param vector 2- or 3-dimensional Dynamic that returns a 2- or 3-dimensional Point which
770
 *               represents the vector the Center of the Effect is currently being dragged with.
771
 * @param region Region that masks the effect of the Distortion.
772
 * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
773
 *               the Center of the Effect.
774
 * @return       ID of the effect added, or -1 if we failed to add one. 
775
 */
776
  public long distort(Dynamic vector, Static4D region, Dynamic2D center)
777
    {  
778
    return mV.add(EffectNames.DISTORT, vector, region, center);
779
    }
780

    
781
///////////////////////////////////////////////////////////////////////////////////////////////////
782
/**
783
 * Distort part of the Object by a (possibly changing in time) vector of force.
784
 * <p>
785
 * Difference between this and the previous method is that here the center of the Effect stays constant.
786
 *   
787
 * @param vector 2- or 3-dimensional Dynamic that returns a 2- or 3-dimensional Point which
788
 *               represents the vector the Center of the Effect is currently being dragged with.
789
 * @param region Region that masks the effect of the Distortion.
790
 * @param center Center of the Effect.
791
 * @return       ID of the effect added, or -1 if we failed to add one. 
792
 */
793
  public long distort(Dynamic vector, Static4D region, Static2D center)
794
    {  
795
    return mV.add(EffectNames.DISTORT, vector, region, center);
796
    }
797

    
798
///////////////////////////////////////////////////////////////////////////////////////////////////
799
/**
800
 * Distort the whole Object by a (possibly changing in time) vector of force.
801
 * 
802
 * @param vector 2- or 3-dimensional Dynamic that returns a 2- or 3-dimensional Point which
803
 *               represents the vector the Center of the Effect is currently being dragged with.
804
 * @param center Center of the Effect.
805
 * @return       ID of the effect added, or -1 if we failed to add one.
806
 */
807
  public long distort(Dynamic vector, Static2D center)
808
    {
809
    return mV.add(EffectNames.DISTORT, vector, null, center);
810
    }
811

    
812
///////////////////////////////////////////////////////////////////////////////////////////////////
813
/**
814
 * Distort part of the Object by a vector of force that changes from (0,0,0) to v.
815
 * 
816
 * @param vector   Maximum vector of force. 
817
 * @param region   Region that masks the effect of the Distortion.
818
 * @param center   Center of the Effect.
819
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
820
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
821
 * @return         ID of the effect added, or -1 if we failed to add one. 
822
 */
823
  public long distort(Static3D vector, Static4D region, Static2D center, int duration, float count)
824
    {  
825
    Dynamic3D di = new Dynamic3D();
826
    di.setCount(count);
827
    di.setDuration(duration);
828
    di.add(new Static3D(0.0f,0.0f,0.0f));
829
    di.add(vector);                                                  
830
           
831
    return mV.add(EffectNames.DISTORT, di, region, center);
832
    }
833

    
834
///////////////////////////////////////////////////////////////////////////////////////////////////
835
/**
836
 * Distort the whole Object by a vector of force that changes from (0,0,0) to v.
837
 * 
838
 * @param vector   Maximum vector of force.
839
 * @param center   Center of the Effect.
840
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
841
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
842
 * @return         ID of the effect added, or -1 if we failed to add one. 
843
 */
844
  public long distort(Static3D vector, Static2D center, int duration, float count)
845
    {
846
    Dynamic3D di = new Dynamic3D();
847
    di.setCount(count);
848
    di.setDuration(duration);
849
    di.add(new Static3D(0.0f,0.0f,0.0f));
850
    di.add(vector);                                                 
851
           
852
    return mV.add(EffectNames.DISTORT, di, null, center);
853
    }
854

    
855
///////////////////////////////////////////////////////////////////////////////////////////////////
856
/**
857
 * Distort the whole Object by a vector of force that changes from (0,0,0) to v.
858
 * <p>
859
 * Difference between this and the previous method is that here the vector of force will get interpolated
860
 * to the maximum v and the effect will end. We are thus limited to count=0.5.
861
 * 
862
 * @param vector   Maximum, final vector of force.
863
 * @param center   Center of the Effect.
864
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
865
 * @return         ID of the effect added, or -1 if we failed to add one. 
866
 */
867
  public long distort(Static3D vector, Static2D center, int duration)
868
    {
869
    Dynamic3D di = new Dynamic3D();
870
    di.setCount(0.5f);
871
    di.setDuration(duration);
872
    di.add(new Static3D(0.0f,0.0f,0.0f));
873
    di.add(vector);                 
874
           
875
    return mV.add(EffectNames.DISTORT, di, null, center);
876
    }
877

    
878
///////////////////////////////////////////////////////////////////////////////////////////////////
879
/**
880
 * Distort the whole Object by a vector of force v.
881
 * <p>
882
 * Here we apply a constant vector of force.
883
 * 
884
 * @param vector Vector of force.
885
 * @param center Center of the Effect.
886
 * @return       ID of the effect added, or -1 if we failed to add one. 
887
 */
888
  public long distort(Static3D vector, Static2D center )
889
    {
890
    Dynamic3D di = new Dynamic3D();
891
    di.setCount(0.5f);
892
    di.setDuration(0);
893
    di.add(new Static3D(0.0f,0.0f,0.0f));
894
    di.add(vector);           
895
           
896
    return mV.add(EffectNames.DISTORT, di, null, center);
897
    }
898

    
899
///////////////////////////////////////////////////////////////////////////////////////////////////
900
///////////////////////////////////////////////////////////////////////////////////////////////////
901
// DEFORM
902
/**
903
 * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
904
 * a (possibly changing in time) point on the Object.
905
 *     
906
 * @param vector Dynamic that, at any given time, returns a Static2D representing vector of
907
 *               force that deforms the shape of the whole Object.
908
 * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
909
 *               the Center of the Effect.
910
 * @return       ID of the effect added, or -1 if we failed to add one.
911
 */
912
  public long deform(Dynamic vector, Dynamic2D center)
913
    {  
914
    return mV.add(EffectNames.DEFORM, vector, null, center);
915
    }
916

    
917
///////////////////////////////////////////////////////////////////////////////////////////////////
918
/**
919
 * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
920
 * a constant point on the Object.
921
 * 
922
 * @param vector Dynamic that, at any given time, returns a Static2D representing
923
 *               vector of force that deforms the shape of the whole Object.
924
 * @param center Center of the Effect.
925
 * @return       ID of the effect added, or -1 if we failed to add one.
926
 */
927
  public long deform(Dynamic vector, Static2D center)
928
    {
929
    return mV.add(EffectNames.DEFORM, vector, null, center);
930
    }
931

    
932
///////////////////////////////////////////////////////////////////////////////////////////////////
933
/**
934
 * Deform the shape of the whole Object with a vector of force smoothly changing from (0,0,0) to v
935
 * applied to a constant point on the Object.
936
 * 
937
 * @param vector   Vector of force.
938
 * @param center   Center of the Effect.
939
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
940
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
941
 * @return         ID of the effect added, or -1 if we failed to add one. 
942
 */
943
  public long deform(Static3D vector, Static2D center, int duration, float count)
944
    {
945
    Dynamic3D di = new Dynamic3D();
946
    di.setCount(count);
947
    di.setDuration(duration);
948
    di.add(new Static3D(0.0f,0.0f,0.0f));
949
    di.add(vector);                
950
           
951
    return mV.add(EffectNames.DEFORM, di, null, center);
952
    }
953

    
954
///////////////////////////////////////////////////////////////////////////////////////////////////
955
/**
956
 * Deform the shape of the whole Object with a vector of force smoothly changing from (0,0,0) to v
957
 * applied to a constant point on the Object.
958
 * <p>
959
 * Identical to calling the previous method with count=0.5.
960
 * 
961
 * @param vector   Final vector of force.
962
 * @param center   Center of the Effect.
963
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
964
 * @return         ID of the effect added, or -1 if we failed to add one. 
965
 */
966
  public long deform(Static3D vector, Static2D center, int duration)
967
    {
968
    Dynamic3D di = new Dynamic3D();
969
    di.setCount(0.5f);
970
    di.setDuration(duration);
971
    di.add(new Static3D(0.0f,0.0f,0.0f));
972
    di.add(vector);             
973
           
974
    return mV.add(EffectNames.DEFORM, di, null, center);
975
    }
976

    
977
///////////////////////////////////////////////////////////////////////////////////////////////////
978
/**
979
 * Deform the shape of the whole Object with a constant vector of force applied to a constant
980
 * point on the Object.
981
 * 
982
 * @param vector Vector of force.
983
 * @param center Center of the Effect.
984
 * @return       ID of the effect added, or -1 if we failed to add one. 
985
 */
986
  public long deform(Static3D vector, Static2D center )
987
    {
988
    Dynamic3D di = new Dynamic3D();
989
    di.setCount(0.5f);
990
    di.setDuration(0);
991
    di.add(new Static3D(0.0f,0.0f,0.0f));
992
    di.add(vector);            
993
           
994
    return mV.add(EffectNames.DEFORM, di, null, center);
995
    }
996
   
997
///////////////////////////////////////////////////////////////////////////////////////////////////  
998
///////////////////////////////////////////////////////////////////////////////////////////////////
999
// SINK
1000
/**
1001
 * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
1002
 * away from the center (degree<=1)
1003
 *    
1004
 * @param sink   1-dimensional Dynamic which, at any given time, returns a Point1D representing
1005
 *               the current degree of the effect.
1006
 * @param region Region that masks the effect of the Sink.
1007
 * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
1008
 *               the Center of the Effect.
1009
 * @return       ID of the effect added, or -1 if we failed to add one. 
1010
 */
1011
  public long sink(Dynamic1D sink, Static4D region, Dynamic2D center)
1012
    {
1013
    return mV.add(EffectNames.SINK, sink, region, center);
1014
    }
1015

    
1016
///////////////////////////////////////////////////////////////////////////////////////////////////
1017
/**
1018
 * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
1019
 * away from the center (degree<=1).
1020
 * <p>
1021
 * Here the Center stays constant.
1022
 *      
1023
 * @param sink   1-dimensional Dynamic which, at any given time, returns a Point1D
1024
 *               representing the current degree of the effect.
1025
 * @param region Region that masks the effect of the Sink.
1026
 * @param center Center of the Effect.
1027
 * @return       ID of the effect added, or -1 if we failed to add one. 
1028
 */
1029
  public long sink(Dynamic1D sink, Static4D region, Static2D center)
1030
    {
1031
    return mV.add(EffectNames.SINK, sink, region, center);
1032
    }
1033
  
1034
///////////////////////////////////////////////////////////////////////////////////////////////////
1035
/**
1036
 * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
1037
 * away from the center (degree<=1).
1038
 * <p>
1039
 * Here we can only interpolate between 1 and degree.
1040
 * 
1041
 * @param sink     How much to push or pull. Between 0 and infinity.
1042
 * @param region   Region that masks the effect of the Sink.
1043
 * @param center   2-dimensional Dynamic that, at any given time, returns a Point2D representing
1044
 *                 the Center of the Effect.
1045
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
1046
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
1047
 * @return         ID of the effect added, or -1 if we failed to add one. 
1048
 */
1049
  public long sink(float sink, Static4D region, Dynamic2D center, int duration, float count)
1050
    {
1051
    Dynamic1D di = new Dynamic1D();
1052
    di.setCount(count);
1053
    di.setDuration(duration);
1054
    di.add(new Static1D(1));
1055
    di.add(new Static1D(sink));
1056
    
1057
    return mV.add(EffectNames.SINK, di, region, center);
1058
    }
1059

    
1060
///////////////////////////////////////////////////////////////////////////////////////////////////
1061
/**
1062
 * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
1063
 * away from the center (degree<=1).
1064
 *   
1065
 * @param sink     How much to push or pull. Between 0 and infinity.
1066
 * @param region   Region that masks the effect of the Sink.
1067
 * @param center   Center of the Effect.
1068
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
1069
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
1070
 * @return         ID of the effect added, or -1 if we failed to add one. 
1071
 */
1072
  public long sink(float sink, Static4D region, Static2D center, int duration, float count)
1073
    {
1074
    Dynamic1D di = new Dynamic1D();
1075
    di.setCount(count);
1076
    di.setDuration(duration);
1077
    di.add(new Static1D(1));
1078
    di.add(new Static1D(sink));
1079
    
1080
    return mV.add(EffectNames.SINK, di, region, center);
1081
    }
1082

    
1083
///////////////////////////////////////////////////////////////////////////////////////////////////
1084
/**
1085
 * Pull all points of the Object towards the center of the Effect (if degree>=1) or push them
1086
 * away from the center (degree<=1).
1087
 * 
1088
 * @param sink     How much to push or pull. Between 0 and infinity.
1089
 * @param center   Center of the Effect.
1090
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
1091
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
1092
 * @return         ID of the effect added, or -1 if we failed to add one. 
1093
 */
1094
  public long sink(float sink, Static2D center, int duration, float count)
1095
    {
1096
    Dynamic1D di = new Dynamic1D();
1097
    di.setCount(count);
1098
    di.setDuration(duration);
1099
    di.add(new Static1D(1));
1100
    di.add(new Static1D(sink));
1101
         
1102
    return mV.add(EffectNames.SINK, di, null, center);
1103
    }
1104

    
1105
///////////////////////////////////////////////////////////////////////////////////////////////////
1106
/**
1107
 * Pull all points of the Object towards the center of the Effect (if degree>=1) or push them
1108
 * away from the center (degree<=1).
1109
 * <p>
1110
 * Equivalent to calling the previous method with count=0.5.
1111
 * 
1112
 * @param sink     How much to push or pull. Between 0 and infinity.
1113
 * @param center   Center of the Effect.
1114
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
1115
 * @return         ID of the effect added, or -1 if we failed to add one. 
1116
 */
1117
  public long sink(float sink, Static2D center, int duration)
1118
    {
1119
    Dynamic1D di = new Dynamic1D();
1120
    di.setCount(0.5f);
1121
    di.setDuration(duration);
1122
    di.add(new Static1D(1));
1123
    di.add(new Static1D(sink));
1124
        
1125
    return mV.add(EffectNames.SINK, di, null, center);
1126
    }
1127

    
1128
///////////////////////////////////////////////////////////////////////////////////////////////////
1129
/**
1130
 * Pull all points of the Object towards the center of the Effect (if degree>=1) or push them
1131
 * away from the center (degree<=1).
1132
 * <p>
1133
 * Equivalent of calling the previous method with duration=0; i.e. we pull immediately.
1134
 * 
1135
 * @param sink   How much to push or pull. Between 0 and infinity.
1136
 * @param center Center of the Effect.
1137
 * @return       ID of the effect added, or -1 if we failed to add one. 
1138
 */
1139
  public long sink(float sink, Static2D center)
1140
    {
1141
    Dynamic1D di = new Dynamic1D();
1142
    di.setCount(0.5f);
1143
    di.setDuration(0);
1144
    di.add(new Static1D(1));
1145
    di.add(new Static1D(sink));
1146
        
1147
    return mV.add(EffectNames.SINK, di, null, center);
1148
    }
1149
  
1150
///////////////////////////////////////////////////////////////////////////////////////////////////  
1151
///////////////////////////////////////////////////////////////////////////////////////////////////
1152
// SWIRL
1153
/**
1154
 * Rotate part of the Object around the Center of the Effect by a certain angle (as returned by the
1155
 * Dynamic).
1156
 *   
1157
 * @param swirl  1-dimensional Dynamic which, at any given time, returns a Point1D representing
1158
 *               the degree of Swirl.
1159
 * @param region Region that masks the effect of the Swirl.
1160
 * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
1161
 *               the Center of the Effect.
1162
 * @return       ID of the effect added, or -1 if we failed to add one. 
1163
 */
1164
  public long swirl(Dynamic1D swirl, Static4D region, Dynamic2D center)
1165
    {    
1166
    return mV.add(EffectNames.SWIRL, swirl, region, center);
1167
    }
1168

    
1169
///////////////////////////////////////////////////////////////////////////////////////////////////
1170
/**
1171
 * Rotate part of the Object around the Center of the Effect by a certain angle (as returned by the
1172
 * Dynamic).
1173
 * <p>
1174
 * Here the Center stays constant.
1175
 *      
1176
 * @param swirl  1-dimensional Dynamic which, at any given time, returns a Point1D representing
1177
 *               the degree of Swirl.
1178
 * @param region Region that masks the effect of the Swirl.
1179
 * @param center Center of the Effect.
1180
 * @return       ID of the effect added, or -1 if we failed to add one. 
1181
 */
1182
  public long swirl(Dynamic1D swirl, Static4D region, Static2D center)
1183
    {    
1184
    return mV.add(EffectNames.SWIRL, swirl, region, center);
1185
    }
1186
 
1187
///////////////////////////////////////////////////////////////////////////////////////////////////
1188
/**
1189
 * Rotate part of the Object around the Center of the Effect by 'degree' angle.
1190
 *   
1191
 * @param swirl    Angle of rotation. Unit: degrees.
1192
 * @param region   Region that masks the effect of the Swirl.
1193
 * @param center   2-dimensional Dynamic that, at any given time, returns a Point2D representing
1194
 *                 the Center of the Effect.
1195
 * @return         ID of the effect added, or -1 if we failed to add one.
1196
 */
1197
  public long swirl(int swirl, Static4D region, Dynamic2D center)
1198
    {
1199
    Dynamic1D di = new Dynamic1D();
1200
    di.setCount(0.5f);
1201
    di.setDuration(0);
1202
    di.add(new Static1D(0));
1203
    di.add(new Static1D(swirl));
1204
    
1205
    return mV.add(EffectNames.SWIRL, di, region, center);
1206
    }
1207

    
1208
///////////////////////////////////////////////////////////////////////////////////////////////////
1209
/**
1210
 * Rotate part of the Object around the Center of the Effect by 'degree' angle.
1211
 * <p>
1212
 * Here the Center stays constant.
1213
 *    
1214
 * @param swirl    Angle of rotation. Unit: degrees.
1215
 * @param region   Region that masks the effect of the Swirl.
1216
 * @param center   Center of the Effect.
1217
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
1218
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
1219
 * @return         ID of the effect added, or -1 if we failed to add one. 
1220
 */
1221
  public long swirl(int swirl, Static4D region, Static2D center, int duration, float count)
1222
    {
1223
    Dynamic1D di = new Dynamic1D();
1224
    di.setCount(count);
1225
    di.setDuration(duration);
1226
    di.add(new Static1D(0));
1227
    di.add(new Static1D(swirl));
1228
    
1229
    return mV.add(EffectNames.SWIRL, di, region, center);
1230
    }
1231

    
1232
///////////////////////////////////////////////////////////////////////////////////////////////////
1233
/**
1234
 * Rotate the whole Object around the Center of the Effect by 'degree' angle.
1235
 * 
1236
 * @param swirl    Angle of rotation. Unit: degrees.
1237
 * @param center   Center of the Effect.
1238
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
1239
 * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
1240
 * @return         ID of the effect added, or -1 if we failed to add one. 
1241
 */
1242
  public long swirl(int swirl, Static2D center, int duration, float count)
1243
    {
1244
    Dynamic1D di = new Dynamic1D();
1245
    di.setCount(count);
1246
    di.setDuration(duration);
1247
    di.add(new Static1D(0));
1248
    di.add(new Static1D(swirl));
1249
         
1250
    return mV.add(EffectNames.SWIRL, di, null, center);
1251
    }
1252

    
1253
///////////////////////////////////////////////////////////////////////////////////////////////////
1254
/**
1255
 * Rotate the whole Object around the Center of the Effect by 'degree' angle.
1256
 * <p>
1257
 * Equivalent to calling the previous method with count=0.5.
1258
 * 
1259
 * @param swirl    Angle of rotation. Unit: degrees.
1260
 * @param center   Center of the Effect.
1261
 * @param duration Time, in milliseconds, it takes to do one full interpolation.
1262
 * @return         ID of the effect added, or -1 if we failed to add one. 
1263
 */
1264
  public long swirl(int swirl, Static2D center, int duration)
1265
    {
1266
    Dynamic1D di = new Dynamic1D();
1267
    di.setCount(0.5f);
1268
    di.setDuration(duration);
1269
    di.add(new Static1D(0));
1270
    di.add(new Static1D(swirl));
1271
        
1272
    return mV.add(EffectNames.SWIRL, di, null, center);
1273
    }
1274

    
1275
///////////////////////////////////////////////////////////////////////////////////////////////////
1276
/**
1277
 * Rotate the whole Object around the Center of the Effect by 'degree' angle.
1278
 * <p>
1279
 * Equivalent to calling the previous method with duration=0.
1280
 * 
1281
 * @param swirl  Angle of rotation. Unit: degrees.
1282
 * @param center Center of the Effect.
1283
 * @return       ID of the effect added, or -1 if we failed to add one. 
1284
 */
1285
  public long swirl(int swirl, Static2D center)
1286
    {
1287
    Dynamic1D di = new Dynamic1D();
1288
    di.setCount(0.5f);
1289
    di.setDuration(0);
1290
    di.add(new Static1D(0));
1291
    di.add(new Static1D(swirl));
1292
        
1293
    return mV.add(EffectNames.SWIRL, di, null, center);
1294
    }
1295

    
1296
///////////////////////////////////////////////////////////////////////////////////////////////////
1297
///////////////////////////////////////////////////////////////////////////////////////////////////
1298
// WAVE
1299

    
1300
}
(7-7/17)