Revision 9aabc9eb
Added by Leszek Koltunski almost 3 years ago
src/main/java/org/distorted/library/type/Dynamic.java | ||
---|---|---|
55 | 55 |
|
56 | 56 |
public abstract class Dynamic |
57 | 57 |
{ |
58 |
/** |
|
59 |
* Keep the speed of interpolation always changing. Time to cover one segment (distance between |
|
60 |
* two consecutive points) always the same. Smoothly interpolate the speed between two segments. |
|
61 |
*/ |
|
62 |
public static final int SPEED_MODE_SMOOTH = 0; |
|
63 |
/** |
|
64 |
* Make each segment have constant speed. Time to cover each segment is still the same, thus the |
|
65 |
* speed will jump when passing through a point and then keep constant. |
|
66 |
*/ |
|
67 |
public static final int SPEED_MODE_SEGMENT_CONSTANT = 1; |
|
68 |
/** |
|
69 |
* Have the speed be always, globally the same across all segments. Time to cover one segment will |
|
70 |
* thus generally no longer be the same. |
|
71 |
*/ |
|
72 |
public static final int SPEED_MODE_GLOBALLY_CONSTANT = 2; |
|
73 |
|
|
58 | 74 |
/** |
59 | 75 |
* One revolution takes us from the first point to the last and back to first through the shortest path. |
60 | 76 |
*/ |
... | ... | |
92 | 108 |
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. |
93 | 109 |
protected double mLastPos; |
94 | 110 |
protected int mAccessType; |
111 |
protected int mSpeedMode; |
|
95 | 112 |
|
96 | 113 |
protected class VectorNoise |
97 | 114 |
{ |
... | ... | |
123 | 140 |
protected float[][] baseV; |
124 | 141 |
|
125 | 142 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
126 |
// the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx etc.
|
|
127 |
// (tangent) is the vector tangent to the path.
|
|
143 |
// the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = a[0]*T^3 + b[0]*T^2 + c[0]*t + d[0] etc.
|
|
144 |
// (velocity) is the velocity vector.
|
|
128 | 145 |
// (cached) is the original vector from vv (copied here so when interpolating we can see if it is |
129 | 146 |
// still valid and if not - rebuild the Cache |
130 | 147 |
|
... | ... | |
134 | 151 |
float[] b; |
135 | 152 |
float[] c; |
136 | 153 |
float[] d; |
137 |
float[] tangent;
|
|
154 |
float[] velocity;
|
|
138 | 155 |
float[] cached; |
156 |
float[] path_ratio; |
|
139 | 157 |
|
140 | 158 |
VectorCache() |
141 | 159 |
{ |
... | ... | |
143 | 161 |
b = new float[mDimension]; |
144 | 162 |
c = new float[mDimension]; |
145 | 163 |
d = new float[mDimension]; |
146 |
tangent = new float[mDimension]; |
|
147 |
cached = new float[mDimension]; |
|
164 |
|
|
165 |
velocity = new float[mDimension]; |
|
166 |
cached = new float[mDimension]; |
|
167 |
path_ratio = new float[NUM_RATIO]; |
|
148 | 168 |
} |
149 | 169 |
} |
150 | 170 |
|
151 | 171 |
protected Vector<VectorCache> vc; |
152 |
protected VectorCache tmp1, tmp2;
|
|
172 |
protected VectorCache tmpCache1, tmpCache2;
|
|
153 | 173 |
protected float mConvexity; |
154 | 174 |
|
175 |
private static final int NUM_RATIO = 10; // we attempt to 'smooth out' the speed in each segment - |
|
176 |
// remember this many 'points' inside the Cache for each segment. |
|
177 |
|
|
178 |
protected static final float[] mTmpRatio = new float[NUM_RATIO]; |
|
179 |
|
|
155 | 180 |
private float[] buf; |
156 | 181 |
private float[] old; |
157 | 182 |
private static final Random mRnd = new Random(); |
... | ... | |
184 | 209 |
mSegment = -1; |
185 | 210 |
mLastPos = -1; |
186 | 211 |
mAccessType= ACCESS_TYPE_RANDOM; |
212 |
mSpeedMode = SPEED_MODE_SMOOTH; |
|
187 | 213 |
mConvexity = 1.0f; |
188 | 214 |
mStartTime = -1; |
189 | 215 |
mCorrectedTime = 0; |
... | ... | |
208 | 234 |
mPausedTime = System.currentTimeMillis(); |
209 | 235 |
} |
210 | 236 |
|
237 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
238 |
|
|
239 |
private float valueAtPoint(float t, VectorCache cache) |
|
240 |
{ |
|
241 |
float tmp,sum = 0.0f; |
|
242 |
|
|
243 |
for(int d=0; d<mDimension; d++) |
|
244 |
{ |
|
245 |
tmp = (3*cache.a[d]*t + 2*cache.b[d])*t + cache.c[d]; |
|
246 |
sum += tmp*tmp; |
|
247 |
} |
|
248 |
|
|
249 |
return (float)Math.sqrt(sum); |
|
250 |
} |
|
251 |
|
|
252 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
253 |
|
|
254 |
protected float smoothSpeed(float time, VectorCache cache) |
|
255 |
{ |
|
256 |
float fndex = time*NUM_RATIO; |
|
257 |
int index = (int)fndex; |
|
258 |
float prev = index==0 ? 0.0f : cache.path_ratio[index-1]; |
|
259 |
float next = cache.path_ratio[index]; |
|
260 |
|
|
261 |
return prev + (next-prev)*(fndex-index); |
|
262 |
} |
|
263 |
|
|
264 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
265 |
// First, compute the approx length of the segment from time=0 to time=(i+1)/NUM_TIME and store this |
|
266 |
// in cache.path_ratio[i]. Then the last path_ratio is the length from 0 to 1, i.e. the total length |
|
267 |
// of the segment. |
|
268 |
// We do this by computing the integral from 0 to 1 of sqrt( (dx/dt)^2 + (dy/dt)^2 ) (i.e. the length |
|
269 |
// of the segment) using the approx 'trapezoids' integration method. |
|
270 |
// |
|
271 |
// Then, for every i, divide path_ratio[i] by the total length to get the percentage of total path |
|
272 |
// length covered at time i. At this time, path_ratio[3] = 0.45 means 'at time 3/NUM_RATIO, we cover |
|
273 |
// 0.45 = 45% of the total length of the segment. |
|
274 |
// |
|
275 |
// Finally, invert this function (for quicker lookups in smoothSpeed) so that after this step, |
|
276 |
// path_ratio[3] = 0.45 means 'at 45% of the time, we cover 3/NUM_RATIO distance'. |
|
277 |
|
|
278 |
protected void smoothOutSegment(VectorCache cache) |
|
279 |
{ |
|
280 |
float vPrev, sum = 0.0f; |
|
281 |
float vNext = valueAtPoint(0.0f,cache); |
|
282 |
|
|
283 |
for(int i=0; i<NUM_RATIO; i++) |
|
284 |
{ |
|
285 |
vPrev = vNext; |
|
286 |
vNext = valueAtPoint( (float)(i+1)/NUM_RATIO,cache); |
|
287 |
sum += (vPrev+vNext); |
|
288 |
cache.path_ratio[i] = sum; |
|
289 |
} |
|
290 |
|
|
291 |
float total = cache.path_ratio[NUM_RATIO-1]; |
|
292 |
|
|
293 |
for(int i=0; i<NUM_RATIO; i++) cache.path_ratio[i] /= total; |
|
294 |
|
|
295 |
int writeIndex = 0; |
|
296 |
float prev=0.0f, next, ratio= 1.0f/NUM_RATIO; |
|
297 |
|
|
298 |
for(int readIndex=0; readIndex<NUM_RATIO; readIndex++) |
|
299 |
{ |
|
300 |
next = cache.path_ratio[readIndex]; |
|
301 |
|
|
302 |
while( prev<ratio && ratio<=next ) |
|
303 |
{ |
|
304 |
float a = (next-ratio)/(next-prev); |
|
305 |
mTmpRatio[writeIndex] = (readIndex+1-a)/NUM_RATIO; |
|
306 |
writeIndex++; |
|
307 |
ratio = (writeIndex+1.0f)/NUM_RATIO; |
|
308 |
} |
|
309 |
|
|
310 |
prev = next; |
|
311 |
} |
|
312 |
|
|
313 |
System.arraycopy(mTmpRatio, 0, cache.path_ratio, 0, NUM_RATIO); |
|
314 |
} |
|
315 |
|
|
211 | 316 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
212 | 317 |
|
213 | 318 |
protected float noise(float time,int vecNum) |
... | ... | |
340 | 445 |
|
341 | 446 |
if( cosA<0.0f ) |
342 | 447 |
{ |
343 |
/* |
|
344 |
/// DEBUGGING //// |
|
345 |
String s = index+" ("; |
|
346 |
float t; |
|
347 |
|
|
348 |
for(int j=0; j<mDimension; j++) |
|
349 |
{ |
|
350 |
t = ((int)(100*baseV[index][j]))/(100.0f); |
|
351 |
s+=(" "+t); |
|
352 |
} |
|
353 |
s += ") ("; |
|
354 |
|
|
355 |
for(int j=0; j<mDimension; j++) |
|
356 |
{ |
|
357 |
t = ((int)(100*old[j]))/(100.0f); |
|
358 |
s+=(" "+t); |
|
359 |
} |
|
360 |
s+= ")"; |
|
361 |
|
|
362 |
android.util.Log.e("dynamic", "kat: " + s); |
|
363 |
/// END DEBUGGING /// |
|
364 |
*/ |
|
365 | 448 |
for(int j=0; j<mDimension; j++) |
366 | 449 |
baseV[index][j] = -baseV[index][j]; |
367 | 450 |
} |
... | ... | |
658 | 741 |
mLastPos = -1; |
659 | 742 |
} |
660 | 743 |
|
744 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
745 |
/** |
|
746 |
* @return See {@link Dynamic#setSpeedMode(int)} |
|
747 |
*/ |
|
748 |
public float getSpeedMode() |
|
749 |
{ |
|
750 |
return mSpeedMode; |
|
751 |
} |
|
752 |
|
|
753 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
754 |
/** |
|
755 |
* Sets the way we compute the interpolation speed. |
|
756 |
* |
|
757 |
* @param mode {@link Dynamic#SPEED_MODE_SMOOTH} or {@link Dynamic#SPEED_MODE_SEGMENT_CONSTANT} or |
|
758 |
* {@link Dynamic#SPEED_MODE_GLOBALLY_CONSTANT} |
|
759 |
*/ |
|
760 |
public void setSpeedMode(int mode) |
|
761 |
{ |
|
762 |
if( mSpeedMode!=mode ) |
|
763 |
{ |
|
764 |
if( mSpeedMode==SPEED_MODE_SMOOTH ) |
|
765 |
{ |
|
766 |
for(int i=0; i<numPoints; i++) |
|
767 |
{ |
|
768 |
tmpCache1 = vc.elementAt(i); |
|
769 |
smoothOutSegment(tmpCache1); |
|
770 |
} |
|
771 |
} |
|
772 |
|
|
773 |
mSpeedMode = mode; |
|
774 |
} |
|
775 |
} |
|
776 |
|
|
661 | 777 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
662 | 778 |
/** |
663 | 779 |
* Return the Dimension, ie number of floats in a single Point this Dynamic interpolates through. |
Also available in: Unified diff
Dynamics: introduce two speed modes - smooth and segment_constant.
Prepare the third mode - globally_constant.