Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedObject.java @ f2fe7e28

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

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

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

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

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

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
    protected abstract DistortedObject deepCopy(int flags);
70

    
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72

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

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

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

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

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

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

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

    
213
      }
214

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

    
231
      mID = DistortedObjectList.add(this);
232

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

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

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

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

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

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

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

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

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

    
426
      return 0;
427
      }
428

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
763
///////////////////////////////////////////////////////////////////////////////////////////////////
764
// Vertex-based effects  
765
///////////////////////////////////////////////////////////////////////////////////////////////////
766
/**
767
 * Distort a (possibly changing in time) part of the Object by a (possibly changing in time) vector of force.
768
 * <p>
769
 * Only at most one of the 'center' and 'region' can be a Dynamic!
770
 *
771
 * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
772
 *               currently being dragged with.
773
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
774
 * @param region Region that masks the Effect.
775
 * @return       ID of the effect added, or -1 if we failed to add one.
776
 */
777
  public long distort(Data3D vector, Data2D center, Data4D region)
778
    {  
779
    return mV.add(EffectNames.DISTORT, vector, center, region);
780
    }
781

    
782
///////////////////////////////////////////////////////////////////////////////////////////////////
783
/**
784
 * Distort the whole Object by a (possibly changing in time) vector of force.
785
 *
786
 * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
787
 *               currently being dragged with.
788
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
789
 * @return       ID of the effect added, or -1 if we failed to add one.
790
 */
791
public long distort(Data3D vector, Data2D center)
792
  {
793
  return mV.add(EffectNames.DISTORT, vector, center);
794
  }
795

    
796
///////////////////////////////////////////////////////////////////////////////////////////////////
797
/**
798
 * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
799
 * a (possibly changing in time) point on the Object.
800
 *     
801
 * @param vector Vector of force that deforms the shape of the whole Object.
802
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
803
 * @return       ID of the effect added, or -1 if we failed to add one.
804
 */
805
  public long deform(Data3D vector, Data2D center)
806
    {  
807
    return mV.add(EffectNames.DEFORM, vector, center);
808
    }
809

    
810
///////////////////////////////////////////////////////////////////////////////////////////////////  
811
/**
812
 * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
813
 * away from the center (degree<=1)
814
 * <p>
815
 * Only at most one of the 'center' and 'region' can be a Dynamic!
816
 *
817
 * @param sink   The current degree of the Effect.
818
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
819
 * @param region Region that masks the Effect.
820
 * @return       ID of the effect added, or -1 if we failed to add one.
821
 */
822
  public long sink(Data1D sink, Data2D center, Data4D region)
823
    {
824
    return mV.add(EffectNames.SINK, sink, center, region);
825
    }
826

    
827
///////////////////////////////////////////////////////////////////////////////////////////////////
828
/**
829
 * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
830
 * away from the center (degree<=1)
831
 *
832
 * @param sink   The current degree of the Effect.
833
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
834
 * @return       ID of the effect added, or -1 if we failed to add one.
835
 */
836
public long sink(Data1D sink, Data2D center)
837
  {
838
  return mV.add(EffectNames.SINK, sink, center);
839
  }
840

    
841
///////////////////////////////////////////////////////////////////////////////////////////////////  
842
/**
843
 * Rotate part of the Object around the Center of the Effect by a certain angle.
844
 * <p>
845
 * Only at most one of the 'center' and 'region' can be a Dynamic!
846
 *
847
 * @param swirl  The degree of Swirl. Positive values swirl clockwise.
848
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
849
 * @param region Region that masks the Effect.
850
 * @return       ID of the effect added, or -1 if we failed to add one.
851
 */
852
  public long swirl(Data1D swirl, Data2D center, Data4D region)
853
    {    
854
    return mV.add(EffectNames.SWIRL, swirl, center, region);
855
    }
856

    
857
///////////////////////////////////////////////////////////////////////////////////////////////////
858
/**
859
 * Rotate the whole Object around the Center of the Effect by a certain angle.
860
 *
861
 * @param swirl  The degree of Swirl. Positive values swirl clockwise.
862
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
863
 * @return       ID of the effect added, or -1 if we failed to add one.
864
 */
865
public long swirl(Data1D swirl, Data2D center)
866
  {
867
  return mV.add(EffectNames.SWIRL, swirl, center);
868
  }
869
}
(7-7/17)