46 |
46 |
// we have the solution: X(t) = at^3 + bt^2 + ct + d where
|
47 |
47 |
// a = 2*P[i](x) + w[i](x) - 2*P[i+1](x) + w[i+1](x)
|
48 |
48 |
// b = -3*P[i](x) - 2*w[i](x) + 3*P[i+1](x) - w[i+1](x)
|
49 |
|
// c = w[i](x)<br>
|
|
49 |
// c = w[i](x)
|
50 |
50 |
// d = P[i](x)
|
51 |
51 |
//
|
52 |
52 |
// and similarly Y(t) and Z(t).
|
... | ... | |
66 |
66 |
*/
|
67 |
67 |
public static final int MODE_JUMP = 2;
|
68 |
68 |
|
69 |
|
protected static Random mRnd = new Random();
|
70 |
|
|
71 |
|
protected static final int NUM_NOISE = 5; // used iff mNoise>0.0. Number of intermediary points between each pair of adjacent vectors
|
72 |
|
// where we randomize noise factors to make the way between the two vectors not so smooth.
|
73 |
|
|
74 |
69 |
protected int mDimension;
|
75 |
70 |
protected int numPoints;
|
76 |
71 |
protected int mVecCurr;
|
... | ... | |
103 |
98 |
protected float[] mFactor;
|
104 |
99 |
protected float[] mNoise;
|
105 |
100 |
protected float[][] baseV;
|
106 |
|
private float[] buf;
|
107 |
|
private float[] old;
|
108 |
101 |
|
109 |
102 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
110 |
103 |
// the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx etc.
|
... | ... | |
135 |
128 |
protected Vector<VectorCache> vc;
|
136 |
129 |
protected VectorCache tmp1, tmp2;
|
137 |
130 |
|
|
131 |
private float[] buf;
|
|
132 |
private float[] old;
|
|
133 |
private static Random mRnd = new Random();
|
|
134 |
private static final int NUM_NOISE = 5; // used iff mNoise>0.0. Number of intermediary points between each pair of adjacent vectors
|
|
135 |
// where we randomize noise factors to make the way between the two vectors not so smooth.
|
|
136 |
|
|
137 |
//private int lastNon;
|
|
138 |
|
138 |
139 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
139 |
140 |
// hide this from Javadoc
|
140 |
141 |
|
... | ... | |
270 |
271 |
|
271 |
272 |
private void checkBase()
|
272 |
273 |
{
|
273 |
|
float tmp;
|
|
274 |
float tmp, cosA;
|
|
275 |
float[] len= new float[mDimension];
|
|
276 |
boolean error=false;
|
|
277 |
|
|
278 |
for(int i=0; i<mDimension; i++)
|
|
279 |
{
|
|
280 |
len[i] = 0.0f;
|
|
281 |
|
|
282 |
for(int k=0; k<mDimension; k++)
|
|
283 |
{
|
|
284 |
len[i] += baseV[i][k]*baseV[i][k];
|
|
285 |
}
|
|
286 |
|
|
287 |
if( len[i] == 0.0f || len[0]/len[i] < 0.95f || len[0]/len[i]>1.05f )
|
|
288 |
{
|
|
289 |
android.util.Log.e("dynamic", "length of vector "+i+" : "+Math.sqrt(len[i]));
|
|
290 |
error = true;
|
|
291 |
}
|
|
292 |
}
|
274 |
293 |
|
275 |
294 |
for(int i=0; i<mDimension; i++)
|
276 |
295 |
for(int j=i+1; j<mDimension; j++)
|
... | ... | |
282 |
301 |
tmp += baseV[i][k]*baseV[j][k];
|
283 |
302 |
}
|
284 |
303 |
|
285 |
|
android.util.Log.e("dynamic", "vectors "+i+" and "+j+" : "+tmp);
|
286 |
|
}
|
287 |
|
|
288 |
|
for(int i=0; i<mDimension; i++)
|
289 |
|
{
|
290 |
|
tmp = 0.0f;
|
|
304 |
cosA = ( (len[i]==0.0f || len[j]==0.0f) ? 0.0f : tmp/(float)Math.sqrt(len[i]*len[j]));
|
291 |
305 |
|
292 |
|
for(int k=0; k<mDimension; k++)
|
293 |
|
{
|
294 |
|
tmp += baseV[i][k]*baseV[i][k];
|
|
306 |
if( cosA > 0.05f || cosA < -0.05f )
|
|
307 |
{
|
|
308 |
android.util.Log.e("dynamic", "cos angle between vectors "+i+" and "+j+" : "+cosA);
|
|
309 |
error = true;
|
|
310 |
}
|
295 |
311 |
}
|
296 |
312 |
|
297 |
|
android.util.Log.e("dynamic", "length of vector "+i+" : "+Math.sqrt(tmp));
|
298 |
|
}
|
|
313 |
if( error ) printBase("");
|
299 |
314 |
}
|
300 |
315 |
|
301 |
316 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
... | ... | |
393 |
408 |
computeOrthonormalBase();
|
394 |
409 |
}
|
395 |
410 |
|
|
411 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
412 |
// debugging
|
|
413 |
/*
|
|
414 |
protected void computeOrthonormalBaseMoreDebug(float time,VectorCache vc)
|
|
415 |
{
|
|
416 |
for(int i=0; i<mDimension; i++)
|
|
417 |
{
|
|
418 |
baseV[0][i] = (3*vc.a[i]*time+2*vc.b[i])*time+vc.c[i]; // first derivative, i.e. velocity vector
|
|
419 |
baseV[1][i] = 6*vc.a[i]*time+2*vc.b[i]; // second derivative,i.e. acceleration vector
|
|
420 |
}
|
|
421 |
|
|
422 |
float av=0.0f, vv=0.0f;
|
|
423 |
|
|
424 |
android.util.Log.e("dyn3D", " ==> velocity ("+baseV[0][0]+","+baseV[0][1]+","+baseV[0][2]+")");
|
|
425 |
android.util.Log.e("dyn3D", " ==> acceleration ("+baseV[1][0]+","+baseV[1][1]+","+baseV[1][2]+")");
|
|
426 |
|
|
427 |
for(int k=0; k<mDimension; k++)
|
|
428 |
{
|
|
429 |
vv += baseV[0][k]*baseV[0][k];
|
|
430 |
av += baseV[1][k]*baseV[0][k];
|
|
431 |
}
|
|
432 |
|
|
433 |
android.util.Log.e("dyn3D", " ==> av: "+av+" vv="+vv);
|
|
434 |
|
|
435 |
av /= vv;
|
|
436 |
|
|
437 |
for(int k=0;k<mDimension; k++)
|
|
438 |
{
|
|
439 |
baseV[1][k] -= av*baseV[0][k];
|
|
440 |
}
|
|
441 |
|
|
442 |
android.util.Log.e("dyn3D", " ==> second base ("+baseV[1][0]+","+baseV[1][1]+","+baseV[1][2]+")");
|
|
443 |
}
|
|
444 |
*/
|
396 |
445 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
397 |
446 |
// helper function in case we are interpolating through more than 2 points
|
398 |
447 |
|
... | ... | |
400 |
449 |
{
|
401 |
450 |
for(int i=0; i<mDimension; i++)
|
402 |
451 |
{
|
403 |
|
baseV[0][i] = (3*vc.a[i]*time+2*vc.b[i])*time+vc.c[i];
|
404 |
|
baseV[1][i] = 6*vc.a[i]*time+2*vc.b[i];
|
|
452 |
baseV[0][i] = (3*vc.a[i]*time+2*vc.b[i])*time+vc.c[i]; // first derivative, i.e. velocity vector
|
|
453 |
old[i] = baseV[1][i];
|
|
454 |
baseV[1][i] = 6*vc.a[i]*time+2*vc.b[i]; // second derivative,i.e. acceleration vector
|
405 |
455 |
}
|
406 |
456 |
|
407 |
457 |
computeOrthonormalBase();
|
... | ... | |
434 |
484 |
{
|
435 |
485 |
int non_zeros=0;
|
436 |
486 |
int last_non_zero=-1;
|
437 |
|
float value;
|
438 |
|
for(int i=0; i<mDimension; i++)
|
439 |
|
{
|
440 |
|
value = baseV[0][i];
|
|
487 |
float tmp;
|
441 |
488 |
|
442 |
|
if( value != 0.0f )
|
|
489 |
for(int i=0; i<mDimension; i++)
|
|
490 |
if( baseV[0][i] != 0.0f )
|
443 |
491 |
{
|
444 |
492 |
non_zeros++;
|
445 |
493 |
last_non_zero=i;
|
446 |
494 |
}
|
447 |
|
}
|
448 |
|
// velocity is the 0 vector -> two consecutive points we are interpolating
|
449 |
|
if( non_zeros==0 ) // through are identical -> no noise, set the base to 0 vectors.
|
450 |
|
{
|
451 |
|
for(int i=0; i<mDimension-1; i++)
|
452 |
|
for(int j=0; j<mDimension; j++)
|
453 |
|
baseV[i+1][j]= 0.0f;
|
454 |
|
}
|
|
495 |
/*
|
|
496 |
if( last_non_zero != lastNon )
|
|
497 |
android.util.Log.e("dynamic", "lastNon="+lastNon+" last_non_zero="+last_non_zero);
|
|
498 |
*/
|
|
499 |
|
|
500 |
if( non_zeros==0 ) ///
|
|
501 |
{ // velocity is the 0 vector -> two
|
|
502 |
for(int i=0; i<mDimension-1; i++) // consecutive points we are interpolating
|
|
503 |
for(int j=0; j<mDimension; j++) // through are identical -> no noise,
|
|
504 |
baseV[i+1][j]= 0.0f; // set the base to 0 vectors.
|
|
505 |
} ///
|
455 |
506 |
else
|
456 |
507 |
{
|
457 |
|
// We can use (modified!) Gram-Schmidt.
|
458 |
|
//
|
459 |
|
// b[0] = b[0]
|
460 |
|
// b[1] = b[1] - (<b[1],b[0]>/<b[0],b[0]>)*b[0]
|
461 |
|
// b[2] = b[2] - (<b[2],b[0]>/<b[0],b[0]>)*b[0] - (<b[2],b[1]>/<b[1],b[1]>)*b[1]
|
462 |
|
// b[3] = b[3] - (<b[3],b[0]>/<b[0],b[0]>)*b[0] - (<b[3],b[1]>/<b[1],b[1]>)*b[1] - (<b[3],b[2]>/<b[2],b[2]>)*b[2]
|
463 |
|
// (...)
|
464 |
|
// then b[i] = b[i] / |b[i]|
|
465 |
|
|
466 |
|
float tmp;
|
467 |
|
|
468 |
|
for(int i=1; i<mDimension; i++) /// one iteration computes baseV[i][*], the i-th orthonormal vector.
|
469 |
|
{
|
470 |
|
buf[i-1]=0.0f;
|
471 |
|
|
472 |
|
for(int k=0; k<mDimension; k++)
|
473 |
|
{
|
474 |
|
old[k] = baseV[i][k];
|
475 |
|
|
476 |
|
if( (i<=last_non_zero && k==i-1) || (i>=(last_non_zero+1) && k==i) )
|
477 |
|
baseV[i][k]= baseV[0][last_non_zero];
|
478 |
|
else
|
479 |
|
baseV[i][k]= 0.0f;
|
480 |
|
|
481 |
|
value = baseV[i-1][k];
|
482 |
|
buf[i-1] += value*value;
|
483 |
|
}
|
484 |
|
|
485 |
|
for(int j=0; j<i; j++)
|
486 |
|
{
|
487 |
|
tmp = 0.0f;
|
488 |
|
|
489 |
|
for(int k=0;k<mDimension; k++)
|
490 |
|
{
|
491 |
|
tmp += baseV[i][k]*baseV[j][k];
|
492 |
|
}
|
493 |
|
|
494 |
|
tmp /= buf[j];
|
495 |
|
|
496 |
|
for(int k=0;k<mDimension; k++)
|
497 |
|
{
|
498 |
|
baseV[i][k] -= tmp*baseV[j][k];
|
499 |
|
}
|
500 |
|
}
|
501 |
|
|
502 |
|
if( i>=2 ) checkAngle(i);
|
503 |
|
} /// end compute baseV[i][*]
|
504 |
|
|
505 |
|
buf[mDimension-1]=0.0f; /// Normalize
|
506 |
|
for(int k=0; k<mDimension; k++) //
|
507 |
|
{ //
|
508 |
|
value = baseV[mDimension-1][k]; //
|
509 |
|
buf[mDimension-1] += value*value; //
|
510 |
|
} //
|
511 |
|
//
|
512 |
|
for(int i=1; i<mDimension; i++) //
|
513 |
|
{ //
|
514 |
|
tmp = (float)Math.sqrt(buf[0]/buf[i]); //
|
515 |
|
//
|
516 |
|
for(int k=0;k<mDimension; k++) //
|
517 |
|
{ //
|
518 |
|
baseV[i][k] *= tmp; //
|
519 |
|
} //
|
520 |
|
} /// End Normalize
|
|
508 |
for(int i=1; i<mDimension; i++) /// One iteration computes baseV[i][*]
|
|
509 |
{ // (aka b[i]), the i-th orthonormal vector.
|
|
510 |
buf[i-1]=0.0f; //
|
|
511 |
// We can use (modified!) Gram-Schmidt.
|
|
512 |
for(int k=0; k<mDimension; k++) //
|
|
513 |
{ //
|
|
514 |
if( i>=2 ) // b[0] = b[0]
|
|
515 |
{ // b[1] = b[1] - (<b[1],b[0]>/<b[0],b[0]>)*b[0]
|
|
516 |
old[k] = baseV[i][k]; // b[2] = b[2] - (<b[2],b[0]>/<b[0],b[0]>)*b[0] - (<b[2],b[1]>/<b[1],b[1]>)*b[1]
|
|
517 |
baseV[i][k]= (k==i-(last_non_zero>=i?1:0)) ? 1.0f : 0.0f; // b[3] = b[3] - (<b[3],b[0]>/<b[0],b[0]>)*b[0] - (<b[3],b[1]>/<b[1],b[1]>)*b[1] - (<b[3],b[2]>/<b[2],b[2]>)*b[2]
|
|
518 |
} // (...)
|
|
519 |
// then b[i] = b[i] / |b[i]| ( Here really b[i] = b[i] / (|b[0]|/|b[i]|)
|
|
520 |
tmp = baseV[i-1][k]; //
|
|
521 |
buf[i-1] += tmp*tmp; //
|
|
522 |
} //
|
|
523 |
//
|
|
524 |
for(int j=0; j<i; j++) //
|
|
525 |
{ //
|
|
526 |
tmp = 0.0f; //
|
|
527 |
for(int k=0;k<mDimension; k++) tmp += baseV[i][k]*baseV[j][k]; //
|
|
528 |
tmp /= buf[j]; //
|
|
529 |
for(int k=0;k<mDimension; k++) baseV[i][k] -= tmp*baseV[j][k]; //
|
|
530 |
} //
|
|
531 |
//
|
|
532 |
checkAngle(i); //
|
|
533 |
} /// end compute baseV[i][*]
|
|
534 |
|
|
535 |
buf[mDimension-1]=0.0f; /// Normalize
|
|
536 |
for(int k=0; k<mDimension; k++) //
|
|
537 |
{ //
|
|
538 |
tmp = baseV[mDimension-1][k]; //
|
|
539 |
buf[mDimension-1] += tmp*tmp; //
|
|
540 |
} //
|
|
541 |
//
|
|
542 |
for(int i=1; i<mDimension; i++) //
|
|
543 |
{ //
|
|
544 |
tmp = (float)Math.sqrt(buf[0]/buf[i]); //
|
|
545 |
for(int k=0;k<mDimension; k++) baseV[i][k] *= tmp; //
|
|
546 |
} /// End Normalize
|
521 |
547 |
}
|
522 |
548 |
|
|
549 |
//lastNon = last_non_zero;
|
|
550 |
|
523 |
551 |
//printBase("end");
|
524 |
552 |
//checkBase();
|
525 |
553 |
}
|
Next fixes for issues with 'jumping' path when noise is on. (and a whole lot of commented out debugging)