Project

General

Profile

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

library / src / main / java / org / distorted / library / Interpolator.java @ 1e438fc7

1
package org.distorted.library;
2

    
3
import java.util.Random;
4

    
5
///////////////////////////////////////////////////////////////////////////////////////////////////
6
/** A class to interpolate between a List of Float{1,2,3,4}Ds.
7
* <p><ul>
8
* <li>if there is only one Point, just jump to it.
9
* <li>if there are two Points, linearly bounce between them
10
* <li>if there are more, interpolate a loop (or a path!) between them.
11
* </ul>
12
*/
13

    
14
// The way Interpolation between more than 2 Points is done:
15
// 
16
// Def: let w[i] = (w[i](x), w[i](y), w[i](z)) be the direction and speed we have to be flying at Point P[i]
17
//
18
// time it takes to fly though one segment v[i] --> v[i+1] : 0.0 --> 1.0
19
// w[i] should be parallel to v[i+1] - v[i-1]   (cyclic notation)
20
// |w[i]| proportional to | P[i]-P[i+1] |
21
//
22
// Given that the flight route (X(t), Y(t), Z(t)) from P(i) to P(i+1)  (0<=t<=1) has to satisfy
23
// X(0) = P[i  ](x), Y(0)=P[i  ](y), Z(0)=P[i  ](z), X'(0) = w[i  ](x), Y'(0) = w[i  ](y), Z'(0) = w[i  ](z)
24
// X(1) = P[i+1](x), Y(1)=P[i+1](y), Z(1)=P[i+1](z), X'(1) = w[i+1](x), Y'(1) = w[i+1](y), Z'(1) = w[i+1](z)
25
//
26
// we have the solution:  X(t) = at^3 + bt^2 + ct + d where
27
// a =  2*P[i](x) +   w[i](x) - 2*P[i+1](x) + w[i+1](x)
28
// b = -3*P[i](x) - 2*w[i](x) + 3*P[i+1](x) - w[i+1](x)
29
// c = w[i](x)<br>
30
// d = P[i](x)
31
//
32
// and similarly Y(t) and Z(t).
33

    
34
public abstract class Interpolator 
35
  {
36
  /**
37
   * One revolution takes us from the first vector to the last and back to first through the shortest path. 
38
   */
39
  public static final int MODE_LOOP = 0; 
40
  /**
41
   * We come back from the last to the first vector through the same way we got there.
42
   */
43
  public static final int MODE_PATH = 1; 
44
  /**
45
   * We just jump back from the last point to the first.
46
   */
47
  public static final int MODE_JUMP = 2; 
48
 
49
  protected static Random mRnd = new Random();
50
  
51
  protected static final int NUM_NOISE = 5; // used iff mNoise>0.0. Number of intermediary points between each pair of adjacent vectors
52
                                            // where we randomize noise factors to make the way between the two vectors not so smooth.
53
  protected int numPoints;
54
  protected int mVecCurr;    
55
  protected boolean cacheDirty; // VectorCache not up to date
56
  protected int mMode;          // LOOP, PATH or JUMP
57
  protected long mDuration;     // number of miliseconds it takes to do a full loop/path from first vector to the last and back to the first 
58
  protected float mCount;       // number of loops/paths we will do; mCount = 1.5 means we go from the first vector to the last, back to first, and to the last again. 
59
  protected float mNoise;       // how 'smooth' our path form each vector to the next is. mNoise = 0.0 (min) --> completely smooth; mNoise==1.0 (max) --> very uneven
60
  
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62
// hide this from Javadoc
63
  
64
  Interpolator()
65
    {
66
    }
67
  
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69
  
70
  void interpolateMain(float[] buffer, int offset, long currentDuration)
71
    {
72
    if( mDuration<=0.0f ) 
73
      {
74
      interpolate(buffer,offset,mCount-(int)mCount);  
75
      }
76
    else
77
      {
78
      float x = (float)currentDuration/mDuration;
79
           
80
      if( x<=mCount || mCount<=0.0f )
81
        {
82
        interpolate(buffer,offset,x-(int)x);
83
        }
84
      }
85
    }
86
  
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  boolean interpolateMain(float[] buffer, int offset, long currentDuration, long step)
90
    {
91
    if( mDuration<=0.0f ) 
92
      {
93
      interpolate(buffer,offset,mCount-(int)mCount);
94
      return false;
95
      }
96
     
97
    float x = (float)currentDuration/mDuration;
98
           
99
    if( x<=mCount || mCount<=0.0f )
100
      {
101
      interpolate(buffer,offset,x-(int)x);
102
        
103
      if( currentDuration+step > mDuration*mCount && mCount>0.0f )
104
        {
105
        interpolate(buffer,offset,mCount-(int)mCount);
106
        return true;
107
        }
108
      }
109
    
110
    return false;
111
    }
112
 
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
// internal debugging only!
115
  
116
  String print()
117
    {
118
    return "duration="+mDuration+" count="+mCount+" Noise="+mNoise+" numVectors="+numPoints+" mMode="+mMode;
119
    }
120
  
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
  
123
  abstract void interpolate(float[] buffer, int offset, float time);
124
  abstract void createNoise();
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127
// PUBLIC API
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129
/**
130
 * Sets the mode of the interpolation to Loop, Path or Jump.
131
 * <ul>
132
 * <li>Loop is when we go from the first point all the way to the last, and the back to the first through 
133
 * the shortest way.
134
 * <li>Path is when we come back from the last point back to the first the same way we got there.
135
 * <li>Jump is when we go from first to last and then jump back to the first.
136
 * </ul>
137
 * 
138
 * @param mode {@link Interpolator#MODE_LOOP}, {@link Interpolator#MODE_PATH} or {@link Interpolator#MODE_JUMP}.
139
 */
140

    
141
  public void setMode(int mode)
142
    {
143
    mMode = mode;  
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147
/**
148
 * Returns the number of Float{1,2,3,4}Ds this Interpolator has been fed with.
149
 *   
150
 * @return the number of Float{1,2,3,4}Ds we are currently interpolating through.
151
 */
152
  public synchronized int getNumPoints()
153
    {
154
    return numPoints;  
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158
/**
159
 * Controls how many times we want to interpolate.
160
 * <p>
161
 * Count equal to 1 means 'go from the first Float{1,2,3,4}D to the last and back'. Does not have to be an
162
 * integer - i.e. count=1.5 would mean 'start at the first Point, go to the last, come back to the first, 
163
 * go to the last again and stop'.
164
 * Count<=0 means 'go on interpolating indefinitely'.
165
 * 
166
 * @param count the number of times we want to interpolate between our collection of Float{1,2,3,4}Ds.
167
 */
168
  public void setCount(float count)
169
    {
170
    mCount = count;  
171
    }
172

    
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174
/**
175
 * Sets the time it takes to do one full interpolation.
176
 * 
177
 * @param duration Time, in milliseconds, it takes to do one full interpolation, i.e. go from the first 
178
 *                 Point to the last and back. 
179
 */
180
  
181
  public void setDuration(long duration)
182
    {
183
    mDuration = duration;
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187
/**
188
 * Sets the 'smoothness' of interpolation. 
189
 * <p>
190
 * When Noise=0 (the default), we interpolate between our Points through the most smooth path possible. 
191
 * Increasing noise makes the Interpolator increasingly deviate from this path, pseudo-randomly speeding 
192
 * up and slowing down, etc.
193
 * 
194
 * @param noise The noise level. Permitted range: 0 <= noise <= 1.
195
 */
196
  
197
  public void setNoise(float noise)
198
    {
199
    if( mNoise==0.0f && noise != 0.0f )  
200
      createNoise();
201
   
202
    if( mNoise<0.0f ) mNoise = 0.0f;
203
    if( mNoise>1.0f ) mNoise = 1.0f;
204
   
205
    mNoise = noise;
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209
// end of DistortedInterpolator
210
  }
(25-25/30)