Revision 649544b8
Added by Leszek Koltunski about 8 years ago
src/main/java/org/distorted/library/type/Dynamic.java | ||
---|---|---|
102 | 102 |
|
103 | 103 |
protected Vector<VectorNoise> vn; |
104 | 104 |
protected float[] mFactor; |
105 |
protected float[][] baseV; |
|
106 |
private float[] buffer; |
|
107 |
|
|
108 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
109 |
// the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx etc. |
|
110 |
// (tangent) is the vector tangent to the path. |
|
111 |
// (cached) is the original vector from vv (copied here so when interpolating we can see if it is |
|
112 |
// still valid and if not - rebuild the Cache |
|
113 |
|
|
114 |
protected class VectorCache |
|
115 |
{ |
|
116 |
float[] a; |
|
117 |
float[] b; |
|
118 |
float[] c; |
|
119 |
float[] d; |
|
120 |
float[] tangent; |
|
121 |
float[] cached; |
|
122 |
|
|
123 |
VectorCache(int dim) |
|
124 |
{ |
|
125 |
a = new float[dim]; |
|
126 |
b = new float[dim]; |
|
127 |
c = new float[dim]; |
|
128 |
d = new float[dim]; |
|
129 |
tangent = new float[dim]; |
|
130 |
cached = new float[dim]; |
|
131 |
} |
|
132 |
} |
|
133 |
|
|
134 |
protected Vector<VectorCache> vc; |
|
135 |
protected VectorCache tmp1, tmp2; |
|
105 | 136 |
|
106 | 137 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
107 | 138 |
// hide this from Javadoc |
108 | 139 |
|
109 |
Dynamic() |
|
140 |
protected Dynamic() |
|
141 |
{ |
|
142 |
} |
|
143 |
|
|
144 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
145 |
|
|
146 |
protected Dynamic(int duration, float count, int dimension) |
|
110 | 147 |
{ |
148 |
vc = new Vector<>(); |
|
149 |
vn = null; |
|
150 |
numPoints = 0; |
|
151 |
cacheDirty = false; |
|
152 |
mMode = MODE_LOOP; |
|
153 |
mDuration = duration; |
|
154 |
mCount = count; |
|
155 |
mDimension = dimension; |
|
156 |
|
|
157 |
baseV = new float[mDimension][mDimension]; |
|
158 |
buffer= new float[mDimension]; |
|
111 | 159 |
} |
112 | 160 |
|
113 | 161 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
194 | 242 |
} |
195 | 243 |
} |
196 | 244 |
|
245 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
246 |
// debugging only |
|
247 |
|
|
248 |
private void printBase(String str) |
|
249 |
{ |
|
250 |
String s; |
|
251 |
float t; |
|
252 |
|
|
253 |
for(int i=0; i<mDimension; i++) |
|
254 |
{ |
|
255 |
s = ""; |
|
256 |
|
|
257 |
for(int j=0; j<mDimension; j++) |
|
258 |
{ |
|
259 |
t = ((int)(1000*baseV[i][j]))/(1000.0f); |
|
260 |
s+=(" "+t); |
|
261 |
} |
|
262 |
android.util.Log.e("dynamic", str+" base "+i+" : " + s); |
|
263 |
} |
|
264 |
} |
|
265 |
|
|
266 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
267 |
// debugging only |
|
268 |
|
|
269 |
private void checkBase() |
|
270 |
{ |
|
271 |
float tmp; |
|
272 |
|
|
273 |
for(int i=0; i<mDimension; i++) |
|
274 |
for(int j=i+1; j<mDimension; j++) |
|
275 |
{ |
|
276 |
tmp = 0.0f; |
|
277 |
|
|
278 |
for(int k=0; k<mDimension; k++) |
|
279 |
{ |
|
280 |
tmp += baseV[i][k]*baseV[j][k]; |
|
281 |
} |
|
282 |
|
|
283 |
android.util.Log.e("dynamic", "vectors "+i+" and "+j+" : "+tmp); |
|
284 |
} |
|
285 |
|
|
286 |
for(int i=0; i<mDimension; i++) |
|
287 |
{ |
|
288 |
tmp = 0.0f; |
|
289 |
|
|
290 |
for(int k=0; k<mDimension; k++) |
|
291 |
{ |
|
292 |
tmp += baseV[i][k]*baseV[i][k]; |
|
293 |
} |
|
294 |
|
|
295 |
android.util.Log.e("dynamic", "length of vector "+i+" : "+Math.sqrt(tmp)); |
|
296 |
} |
|
297 |
} |
|
298 |
|
|
299 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
300 |
// helper function in case we are interpolating through exactly 2 points |
|
301 |
|
|
302 |
protected void computeOrthonormalBase2(Static1D curr, Static1D next) |
|
303 |
{ |
|
304 |
switch(mDimension) |
|
305 |
{ |
|
306 |
case 1: baseV[0][0] = (next.x-curr.x); |
|
307 |
break; |
|
308 |
case 2: Static2D curr2 = (Static2D)curr; |
|
309 |
Static2D next2 = (Static2D)next; |
|
310 |
baseV[0][0] = (next2.x-curr2.x); |
|
311 |
baseV[0][1] = (next2.y-curr2.y); |
|
312 |
break; |
|
313 |
case 3: Static3D curr3 = (Static3D)curr; |
|
314 |
Static3D next3 = (Static3D)next; |
|
315 |
baseV[0][0] = (next3.x-curr3.x); |
|
316 |
baseV[0][1] = (next3.y-curr3.y); |
|
317 |
baseV[0][2] = (next3.z-curr3.z); |
|
318 |
break; |
|
319 |
case 4: Static4D curr4 = (Static4D)curr; |
|
320 |
Static4D next4 = (Static4D)next; |
|
321 |
baseV[0][0] = (next4.x-curr4.x); |
|
322 |
baseV[0][1] = (next4.y-curr4.y); |
|
323 |
baseV[0][2] = (next4.z-curr4.z); |
|
324 |
baseV[0][3] = (next4.w-curr4.w); |
|
325 |
break; |
|
326 |
case 5: Static5D curr5 = (Static5D)curr; |
|
327 |
Static5D next5 = (Static5D)next; |
|
328 |
baseV[0][0] = (next5.x-curr5.x); |
|
329 |
baseV[0][1] = (next5.y-curr5.y); |
|
330 |
baseV[0][2] = (next5.z-curr5.z); |
|
331 |
baseV[0][3] = (next5.w-curr5.w); |
|
332 |
baseV[0][4] = (next5.v-curr5.v); |
|
333 |
break; |
|
334 |
default: throw new RuntimeException("Unsupported dimension"); |
|
335 |
} |
|
336 |
|
|
337 |
if( baseV[0][0] == 0.0f ) |
|
338 |
{ |
|
339 |
baseV[1][0] = 1.0f; |
|
340 |
baseV[1][1] = 0.0f; |
|
341 |
} |
|
342 |
else |
|
343 |
{ |
|
344 |
baseV[1][0] = 0.0f; |
|
345 |
baseV[1][1] = 1.0f; |
|
346 |
} |
|
347 |
|
|
348 |
for(int i=2; i<mDimension; i++) |
|
349 |
{ |
|
350 |
baseV[1][i] = 0.0f; |
|
351 |
} |
|
352 |
|
|
353 |
computeOrthonormalBase(); |
|
354 |
} |
|
355 |
|
|
356 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
357 |
// helper function in case we are interpolating through more than 2 points |
|
358 |
|
|
359 |
protected void computeOrthonormalBaseMore(float time,VectorCache vc) |
|
360 |
{ |
|
361 |
for(int i=0; i<mDimension; i++) |
|
362 |
{ |
|
363 |
baseV[0][i] = (3*vc.a[i]*time+2*vc.b[i])*time+vc.c[i]; |
|
364 |
baseV[1][i] = 6*vc.a[i]*time+2*vc.b[i]; |
|
365 |
} |
|
366 |
|
|
367 |
computeOrthonormalBase(); |
|
368 |
} |
|
369 |
|
|
370 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
371 |
// When this function gets called, baseV[0] and baseV[1] should have been filled with two mDimension-al |
|
372 |
// vectors. This function then fills the rest of the baseV array with a mDimension-al Orthonormal base. |
|
373 |
// (mDimension-2 vectors, pairwise orthogonal to each other and to the original 2). The function always |
|
374 |
// leaves base[0] alone but generally speaking must adjust base[1] to make it orthogonal to base[0]! |
|
375 |
// The whole baseV is then used to compute Noise. |
|
376 |
// |
|
377 |
// When computing noise of a point travelling along a N-dimensional path, there are three cases: |
|
378 |
// a) we may be interpolating through 1 point, i.e. standing in place - nothing to do in this case |
|
379 |
// b) we may be interpolating through 2 points, i.e. travelling along a straight line between them - |
|
380 |
// then pass the velocity vector in baseV[0] and anything linearly independent in base[1]. |
|
381 |
// The output will then be discontinuous in dimensions>2 (sad corollary from the Hairy Ball Theorem) |
|
382 |
// but we don't care - we are travelling along a straight line, so velocity (aka baseV[0]!) does |
|
383 |
// not change. |
|
384 |
// c) we may be interpolating through more than 2 points. Then interpolation formulas ensure the path |
|
385 |
// will never be a straight line, even locally -> we can pass in baseV[0] and baseV[1] the velocity |
|
386 |
// and the acceleration (first and second derivatives of the path) which are then guaranteed to be |
|
387 |
// linearly independent. Then we can ensure this is continuous in dimensions <=4. This leaves |
|
388 |
// dimension 5 (ATM WAVE is 5-dimensional) discontinuous -> WAVE will suffer from chaotic noise. |
|
389 |
// |
|
390 |
// Bear in mind here the 'normal' in 'orthonormal' means 'length equal to the length of the original |
|
391 |
// velocity vector' (rather than the standard 1) |
|
392 |
|
|
393 |
protected void computeOrthonormalBase() |
|
394 |
{ |
|
395 |
int non_zeros=0; |
|
396 |
int last_non_zero=-1; |
|
397 |
float value; |
|
398 |
for(int i=0; i<mDimension; i++) |
|
399 |
{ |
|
400 |
value = baseV[0][i]; |
|
401 |
|
|
402 |
if( value != 0.0f ) |
|
403 |
{ |
|
404 |
non_zeros++; |
|
405 |
last_non_zero=i; |
|
406 |
} |
|
407 |
} |
|
408 |
// velocity is the 0 vector -> two consecutive points we are interpolating |
|
409 |
if( non_zeros==0 ) // through are identical -> no noise, set the base to 0 vectors. |
|
410 |
{ |
|
411 |
for(int i=0; i<mDimension-1; i++) |
|
412 |
for(int j=0; j<mDimension; j++) |
|
413 |
baseV[i+1][j]= 0.0f; |
|
414 |
} |
|
415 |
else |
|
416 |
{ |
|
417 |
for(int i=0; i<mDimension-1; i++) |
|
418 |
for(int j=0; j<mDimension; j++) |
|
419 |
{ |
|
420 |
if( (i<last_non_zero && j==i) || (i>=last_non_zero && j==i+1) ) |
|
421 |
baseV[i+1][j]= baseV[0][last_non_zero]; |
|
422 |
else |
|
423 |
baseV[i+1][j]= 0.0f; |
|
424 |
} |
|
425 |
|
|
426 |
// That's it if velocity vector is already one of the standard orthonormal |
|
427 |
// vectors. Otherwise (i.e. non_zeros>1) velocity is linearly independent |
|
428 |
// to what's in baseV right now and we can use (modified!) Gram-Schmidt. |
|
429 |
// |
|
430 |
// b[0] = b[0] |
|
431 |
// b[1] = b[1] - (<b[1],b[0]>/<b[0],b[0]>)*b[0] |
|
432 |
// b[2] = b[2] - (<b[2],b[0]>/<b[0],b[0]>)*b[0] - (<b[2],b[1]>/<b[1],b[1]>)*b[1] |
|
433 |
// 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] |
|
434 |
// |
|
435 |
// then b[i] = b[i] / |b[i]| |
|
436 |
|
|
437 |
if( non_zeros>1 ) |
|
438 |
{ |
|
439 |
float tmp; |
|
440 |
|
|
441 |
for(int i=1; i<mDimension; i++) |
|
442 |
{ |
|
443 |
buffer[i-1]=0.0f; |
|
444 |
|
|
445 |
for(int k=0; k<mDimension; k++) |
|
446 |
{ |
|
447 |
value = baseV[i-1][k]; |
|
448 |
buffer[i-1] += value*value; |
|
449 |
} |
|
450 |
|
|
451 |
for(int j=0; j<i; j++) |
|
452 |
{ |
|
453 |
tmp = 0.0f; |
|
454 |
|
|
455 |
for(int k=0;k<mDimension; k++) |
|
456 |
{ |
|
457 |
tmp += baseV[i][k]*baseV[j][k]; |
|
458 |
} |
|
459 |
|
|
460 |
tmp /= buffer[j]; |
|
461 |
|
|
462 |
for(int k=0;k<mDimension; k++) |
|
463 |
{ |
|
464 |
baseV[i][k] -= tmp*baseV[j][k]; |
|
465 |
} |
|
466 |
} |
|
467 |
} |
|
468 |
|
|
469 |
buffer[mDimension-1]=0.0f; |
|
470 |
for(int k=0; k<mDimension; k++) |
|
471 |
{ |
|
472 |
value = baseV[mDimension-1][k]; |
|
473 |
buffer[mDimension-1] += value*value; |
|
474 |
} |
|
475 |
|
|
476 |
for(int i=1; i<mDimension; i++) |
|
477 |
{ |
|
478 |
tmp = (float)Math.sqrt(buffer[0]/buffer[i]); |
|
479 |
|
|
480 |
for(int k=0;k<mDimension; k++) |
|
481 |
{ |
|
482 |
baseV[i][k] *= tmp; |
|
483 |
} |
|
484 |
} |
|
485 |
} |
|
486 |
} |
|
487 |
|
|
488 |
//printBase("end"); |
|
489 |
//checkBase(); |
|
490 |
} |
|
491 |
|
|
197 | 492 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
198 | 493 |
// internal debugging only! |
199 | 494 |
|
src/main/java/org/distorted/library/type/Dynamic1D.java | ||
---|---|---|
29 | 29 |
|
30 | 30 |
public class Dynamic1D extends Dynamic implements Data1D |
31 | 31 |
{ |
32 |
|
|
33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
34 |
// the coefficients of the X(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx etc. |
|
35 |
// (x) is the vector tangent to the path. |
|
36 |
// (vx) is the original vector from vv (copied here so when interpolating we can see if it is |
|
37 |
// still valid and if not - rebuild the Cache |
|
38 |
|
|
39 |
private class VectorCache |
|
40 |
{ |
|
41 |
float ax, bx, cx, dx; |
|
42 |
|
|
43 |
float x; |
|
44 |
float vx; |
|
45 |
} |
|
46 |
|
|
47 |
private Vector<VectorCache> vc; |
|
48 |
private VectorCache tmp1, tmp2; |
|
49 |
|
|
50 | 32 |
private Vector<Static1D> vv; |
51 | 33 |
private Static1D prev, curr, next; |
52 | 34 |
|
... | ... | |
75 | 57 |
|
76 | 58 |
if( q>1 ) |
77 | 59 |
{ |
78 |
tmp1.x = nx+px/q;
|
|
60 |
tmp1.tangent[0] = nx+px/q;
|
|
79 | 61 |
} |
80 | 62 |
else |
81 | 63 |
{ |
82 |
tmp1.x = px+nx*q;
|
|
64 |
tmp1.tangent[0] = px+nx*q;
|
|
83 | 65 |
} |
84 | 66 |
} |
85 | 67 |
else |
86 | 68 |
{ |
87 |
tmp1.x = 0.0f;
|
|
69 |
tmp1.tangent[0] = 0.0f;
|
|
88 | 70 |
} |
89 | 71 |
} |
90 | 72 |
|
... | ... | |
97 | 79 |
tmp1= vc.elementAt(0); |
98 | 80 |
curr= vv.elementAt(0); |
99 | 81 |
|
100 |
tmp1.ax = 0.0f;
|
|
101 |
tmp1.bx = 0.0f;
|
|
102 |
tmp1.cx = curr.x;
|
|
103 |
tmp1.dx = 0.0f;
|
|
82 |
tmp1.a[0] = 0.0f;
|
|
83 |
tmp1.b[0] = 0.0f;
|
|
84 |
tmp1.c[0] = curr.x;
|
|
85 |
tmp1.d[0] = 0.0f;
|
|
104 | 86 |
} |
105 | 87 |
else if( numPoints==2 ) |
106 | 88 |
{ |
... | ... | |
109 | 91 |
curr= vv.elementAt(0); |
110 | 92 |
next= vv.elementAt(1); |
111 | 93 |
|
112 |
tmp1.ax = 0.0f;
|
|
113 |
tmp1.bx = 0.0f;
|
|
114 |
tmp1.cx = next.x - curr.x;
|
|
115 |
tmp1.dx = curr.x;
|
|
94 |
tmp1.a[0] = 0.0f;
|
|
95 |
tmp1.b[0] = 0.0f;
|
|
96 |
tmp1.c[0] = next.x - curr.x;
|
|
97 |
tmp1.d[0] = curr.x;
|
|
116 | 98 |
|
117 |
tmp2.ax = 0.0f;
|
|
118 |
tmp2.bx = 0.0f;
|
|
119 |
tmp2.cx = curr.x - next.x;
|
|
120 |
tmp2.dx = next.x;
|
|
99 |
tmp2.a[0] = 0.0f;
|
|
100 |
tmp2.b[0] = 0.0f;
|
|
101 |
tmp2.c[0] = curr.x - next.x;
|
|
102 |
tmp2.d[0] = next.x;
|
|
121 | 103 |
} |
122 | 104 |
else |
123 | 105 |
{ |
... | ... | |
134 | 116 |
curr= vv.elementAt(i); |
135 | 117 |
next= vv.elementAt(n); |
136 | 118 |
|
137 |
tmp1.vx = curr.x;
|
|
119 |
tmp1.cached[0] = curr.x;
|
|
138 | 120 |
|
139 |
tmp1.ax = 2*curr.x + tmp1.x - 2*next.x + tmp2.x;
|
|
140 |
tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
|
|
141 |
tmp1.cx = tmp1.x;
|
|
142 |
tmp1.dx = curr.x;
|
|
121 |
tmp1.a[0] = 2*curr.x + tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
|
|
122 |
tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
|
|
123 |
tmp1.c[0] = tmp1.tangent[0];
|
|
124 |
tmp1.d[0] = curr.x;
|
|
143 | 125 |
} |
144 | 126 |
} |
145 | 127 |
|
... | ... | |
154 | 136 |
*/ |
155 | 137 |
public Dynamic1D() |
156 | 138 |
{ |
157 |
this(0,0.5f); |
|
139 |
super(0,0.5f,1); |
|
140 |
vv = new Vector<>(); |
|
158 | 141 |
} |
159 | 142 |
|
160 | 143 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
169 | 152 |
*/ |
170 | 153 |
public Dynamic1D(int duration, float count) |
171 | 154 |
{ |
155 |
super(duration,count,1); |
|
172 | 156 |
vv = new Vector<>(); |
173 |
vc = new Vector<>(); |
|
174 |
vn = null; |
|
175 |
numPoints = 0; |
|
176 |
cacheDirty = false; |
|
177 |
mMode = MODE_LOOP; |
|
178 |
mDuration = duration; |
|
179 |
mCount = count; |
|
180 |
mDimension = 1; |
|
181 | 157 |
} |
182 | 158 |
|
183 | 159 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
237 | 213 |
{ |
238 | 214 |
case 0: |
239 | 215 |
case 1: break; |
240 |
case 2: vc.add(new VectorCache()); |
|
241 |
vc.add(new VectorCache()); |
|
242 |
vc.add(new VectorCache()); |
|
216 |
case 2: vc.add(new VectorCache(1));
|
|
217 |
vc.add(new VectorCache(1));
|
|
218 |
vc.add(new VectorCache(1));
|
|
243 | 219 |
cacheDirty = true; |
244 | 220 |
break; |
245 |
default:vc.add(new VectorCache()); |
|
221 |
default:vc.add(new VectorCache(1));
|
|
246 | 222 |
cacheDirty = true; |
247 | 223 |
} |
248 | 224 |
|
... | ... | |
269 | 245 |
{ |
270 | 246 |
case 0: |
271 | 247 |
case 1: break; |
272 |
case 2: vc.add(new VectorCache()); |
|
273 |
vc.add(new VectorCache()); |
|
274 |
vc.add(new VectorCache()); |
|
248 |
case 2: vc.add(new VectorCache(1));
|
|
249 |
vc.add(new VectorCache(1));
|
|
250 |
vc.add(new VectorCache(1));
|
|
275 | 251 |
cacheDirty = true; |
276 | 252 |
break; |
277 |
default:vc.add(location,new VectorCache()); |
|
253 |
default:vc.add(location,new VectorCache(1));
|
|
278 | 254 |
cacheDirty = true; |
279 | 255 |
} |
280 | 256 |
|
... | ... | |
437 | 413 |
next = vv.elementAt(vecNext); |
438 | 414 |
tmp2 = vc.elementAt(vecNext); |
439 | 415 |
|
440 |
if( tmp2.vx!=next.x ) recomputeCache();
|
|
416 |
if( tmp2.cached[0]!=next.x ) recomputeCache();
|
|
441 | 417 |
} |
442 | 418 |
|
443 | 419 |
if( vn!=null ) |
... | ... | |
446 | 422 |
} |
447 | 423 |
|
448 | 424 |
tmp1 = vc.elementAt(vecCurr); |
449 |
buffer[offset] = ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx;
|
|
425 |
buffer[offset] = ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0];
|
|
450 | 426 |
break; |
451 | 427 |
} |
452 | 428 |
} |
src/main/java/org/distorted/library/type/Dynamic2D.java | ||
---|---|---|
29 | 29 |
|
30 | 30 |
public class Dynamic2D extends Dynamic implements Data2D |
31 | 31 |
{ |
32 |
|
|
33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
34 |
// the coefficients of the X(t), Y(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx etc. |
|
35 |
// (x,y) is the vector tangent to the path. |
|
36 |
// (vx,vy) is the original vector from vv (copied here so when interpolating we can see if it is |
|
37 |
// still valid and if not - rebuild the Cache |
|
38 |
|
|
39 |
private class VectorCache |
|
40 |
{ |
|
41 |
float ax, bx, cx, dx; |
|
42 |
float ay, by, cy, dy; |
|
43 |
|
|
44 |
float x,y; |
|
45 |
float vx,vy; |
|
46 |
} |
|
47 |
|
|
48 |
private Vector<VectorCache> vc; |
|
49 |
private VectorCache tmp1, tmp2; |
|
50 |
|
|
51 | 32 |
private Vector<Static2D> vv; |
52 | 33 |
private Static2D prev, curr, next; |
53 | 34 |
|
... | ... | |
78 | 59 |
|
79 | 60 |
if( q>1 ) |
80 | 61 |
{ |
81 |
tmp1.x = nx+px/q;
|
|
82 |
tmp1.y = ny+py/q;
|
|
62 |
tmp1.tangent[0] = nx+px/q;
|
|
63 |
tmp1.tangent[1] = ny+py/q;
|
|
83 | 64 |
} |
84 | 65 |
else |
85 | 66 |
{ |
86 |
tmp1.x = px+nx*q;
|
|
87 |
tmp1.y = py+ny*q;
|
|
67 |
tmp1.tangent[0] = px+nx*q;
|
|
68 |
tmp1.tangent[1] = py+ny*q;
|
|
88 | 69 |
} |
89 | 70 |
} |
90 | 71 |
else |
91 | 72 |
{ |
92 |
tmp1.x = 0.0f;
|
|
93 |
tmp1.y = 0.0f;
|
|
73 |
tmp1.tangent[0] = 0.0f;
|
|
74 |
tmp1.tangent[1] = 0.0f;
|
|
94 | 75 |
} |
95 | 76 |
} |
96 | 77 |
|
... | ... | |
103 | 84 |
tmp1= vc.elementAt(0); |
104 | 85 |
curr= vv.elementAt(0); |
105 | 86 |
|
106 |
tmp1.ax = tmp1.ay = 0.0f;
|
|
107 |
tmp1.bx = tmp1.by = 0.0f;
|
|
108 |
tmp1.cx = curr.x;
|
|
109 |
tmp1.cy = curr.y;
|
|
110 |
tmp1.dx = tmp1.dy = 0.0f;
|
|
87 |
tmp1.a[0] = tmp1.a[1] = 0.0f;
|
|
88 |
tmp1.b[0] = tmp1.b[1] = 0.0f;
|
|
89 |
tmp1.c[0] = curr.x;
|
|
90 |
tmp1.c[1] = curr.y;
|
|
91 |
tmp1.d[0] = tmp1.d[1] = 0.0f;
|
|
111 | 92 |
} |
112 | 93 |
else if( numPoints==2 ) |
113 | 94 |
{ |
... | ... | |
116 | 97 |
curr= vv.elementAt(0); |
117 | 98 |
next= vv.elementAt(1); |
118 | 99 |
|
119 |
tmp1.ax = tmp1.ay = 0.0f;
|
|
120 |
tmp1.bx = tmp1.by = 0.0f;
|
|
121 |
tmp1.cx = next.x - curr.x;
|
|
122 |
tmp1.cy = next.y - curr.y;
|
|
123 |
tmp1.dx = curr.x;
|
|
124 |
tmp1.dy = curr.y;
|
|
100 |
tmp1.a[0] = tmp1.a[1] = 0.0f;
|
|
101 |
tmp1.b[0] = tmp1.b[1] = 0.0f;
|
|
102 |
tmp1.c[0] = next.x - curr.x;
|
|
103 |
tmp1.c[1] = next.y - curr.y;
|
|
104 |
tmp1.d[0] = curr.x;
|
|
105 |
tmp1.d[1] = curr.y;
|
|
125 | 106 |
|
126 |
tmp2.ax = tmp2.ay = 0.0f;
|
|
127 |
tmp2.bx = tmp2.by = 0.0f;
|
|
128 |
tmp2.cx = curr.x - next.x;
|
|
129 |
tmp2.cy = curr.y - next.y;
|
|
130 |
tmp2.dx = next.x;
|
|
131 |
tmp2.dy = next.y;
|
|
107 |
tmp2.a[0] = tmp2.a[1] = 0.0f;
|
|
108 |
tmp2.b[0] = tmp2.b[1] = 0.0f;
|
|
109 |
tmp2.c[0] = curr.x - next.x;
|
|
110 |
tmp2.c[1] = curr.y - next.y;
|
|
111 |
tmp2.d[0] = next.x;
|
|
112 |
tmp2.d[1] = next.y;
|
|
132 | 113 |
} |
133 | 114 |
else |
134 | 115 |
{ |
... | ... | |
145 | 126 |
curr= vv.elementAt(i); |
146 | 127 |
next= vv.elementAt(n); |
147 | 128 |
|
148 |
tmp1.vx = curr.x;
|
|
149 |
tmp1.vy = curr.y;
|
|
150 |
|
|
151 |
tmp1.ax = 2*curr.x + tmp1.x - 2*next.x + tmp2.x;
|
|
152 |
tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
|
|
153 |
tmp1.cx = tmp1.x;
|
|
154 |
tmp1.dx = curr.x;
|
|
155 |
|
|
156 |
tmp1.ay = 2*curr.y + tmp1.y - 2*next.y + tmp2.y;
|
|
157 |
tmp1.by = -3*curr.y - 2*tmp1.y + 3*next.y - tmp2.y;
|
|
158 |
tmp1.cy = tmp1.y;
|
|
159 |
tmp1.dy = curr.y;
|
|
129 |
tmp1.cached[0] = curr.x;
|
|
130 |
tmp1.cached[1] = curr.y;
|
|
131 |
|
|
132 |
tmp1.a[0] = 2*curr.x + tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
|
|
133 |
tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
|
|
134 |
tmp1.c[0] = tmp1.tangent[0];
|
|
135 |
tmp1.d[0] = curr.x;
|
|
136 |
|
|
137 |
tmp1.a[1] = 2*curr.y + tmp1.tangent[1] - 2*next.y + tmp2.tangent[1];
|
|
138 |
tmp1.b[1] = -3*curr.y - 2*tmp1.tangent[1] + 3*next.y - tmp2.tangent[1];
|
|
139 |
tmp1.c[1] = tmp1.tangent[1];
|
|
140 |
tmp1.d[1] = curr.y;
|
|
160 | 141 |
} |
161 | 142 |
} |
162 | 143 |
|
... | ... | |
171 | 152 |
*/ |
172 | 153 |
public Dynamic2D() |
173 | 154 |
{ |
174 |
this(0,0.5f); |
|
155 |
super(0,0.5f,2); |
|
156 |
vv = new Vector<>(); |
|
175 | 157 |
} |
176 | 158 |
|
177 | 159 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
186 | 168 |
*/ |
187 | 169 |
public Dynamic2D(int duration, float count) |
188 | 170 |
{ |
171 |
super(duration,count,2); |
|
189 | 172 |
vv = new Vector<>(); |
190 |
vc = new Vector<>(); |
|
191 |
vn = null; |
|
192 |
numPoints = 0; |
|
193 |
cacheDirty = false; |
|
194 |
mMode = MODE_LOOP; |
|
195 |
mDuration = duration; |
|
196 |
mCount = count; |
|
197 |
mDimension = 2; |
|
198 | 173 |
} |
199 | 174 |
|
200 | 175 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
254 | 229 |
{ |
255 | 230 |
case 0: |
256 | 231 |
case 1: break; |
257 |
case 2: vc.add(new VectorCache()); |
|
258 |
vc.add(new VectorCache()); |
|
259 |
vc.add(new VectorCache()); |
|
232 |
case 2: vc.add(new VectorCache(2));
|
|
233 |
vc.add(new VectorCache(2));
|
|
234 |
vc.add(new VectorCache(2));
|
|
260 | 235 |
break; |
261 |
default:vc.add(new VectorCache()); |
|
236 |
default:vc.add(new VectorCache(2));
|
|
262 | 237 |
} |
263 | 238 |
|
264 | 239 |
numPoints++; |
... | ... | |
285 | 260 |
{ |
286 | 261 |
case 0: |
287 | 262 |
case 1: break; |
288 |
case 2: vc.add(new VectorCache()); |
|
289 |
vc.add(new VectorCache()); |
|
290 |
vc.add(new VectorCache()); |
|
263 |
case 2: vc.add(new VectorCache(2));
|
|
264 |
vc.add(new VectorCache(2));
|
|
265 |
vc.add(new VectorCache(2));
|
|
291 | 266 |
break; |
292 |
default:vc.add(location,new VectorCache()); |
|
267 |
default:vc.add(location,new VectorCache(2));
|
|
293 | 268 |
} |
294 | 269 |
|
295 | 270 |
numPoints++; |
... | ... | |
417 | 392 |
{ |
418 | 393 |
time = noise(time,0); |
419 | 394 |
|
420 |
float dx2 = next.x-curr.x;
|
|
421 |
float dy2 = next.y-curr.y;
|
|
395 |
baseV[0][0] = next.x-curr.x;
|
|
396 |
baseV[0][1] = next.y-curr.y;
|
|
422 | 397 |
|
423 |
buffer[offset ] = dx2*time + curr.x +dy2*mFactor[0];
|
|
424 |
buffer[offset+1] = dy2*time + curr.y -dx2*mFactor[0];
|
|
398 |
buffer[offset ] = baseV[0][0]*time + curr.x +baseV[0][0]*mFactor[0];
|
|
399 |
buffer[offset+1] = baseV[0][1]*time + curr.y -baseV[0][1]*mFactor[0];
|
|
425 | 400 |
} |
426 | 401 |
else |
427 | 402 |
{ |
... | ... | |
468 | 443 |
next = vv.elementAt(vecNext); |
469 | 444 |
tmp2 = vc.elementAt(vecNext); |
470 | 445 |
|
471 |
if( tmp2.vx!=next.x || tmp2.vy!=next.y ) recomputeCache();
|
|
446 |
if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y ) recomputeCache();
|
|
472 | 447 |
} |
473 |
|
|
448 |
|
|
449 |
tmp1 = vc.elementAt(vecCurr); |
|
450 |
|
|
474 | 451 |
if( vn!=null ) |
475 | 452 |
{ |
476 | 453 |
time = noise(time,vecCurr); |
477 |
tmp1 = vc.elementAt(vecCurr); |
|
478 |
|
|
479 |
float dx2 = (3*tmp1.ax*time+2*tmp1.bx)*time + tmp1.cx; |
|
480 |
float dy2 = (3*tmp1.ay*time+2*tmp1.by)*time + tmp1.cy; |
|
454 |
|
|
455 |
baseV[0][0] = (3*tmp1.a[0]*time+2*tmp1.b[0])*time + tmp1.c[0]; |
|
456 |
baseV[0][1] = (3*tmp1.a[1]*time+2*tmp1.b[1])*time + tmp1.c[1]; |
|
481 | 457 |
|
482 |
buffer[offset ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx +dy2*mFactor[0];
|
|
483 |
buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy -dx2*mFactor[0];
|
|
458 |
buffer[offset ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0] +baseV[0][0]*mFactor[0];
|
|
459 |
buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1] -baseV[0][1]*mFactor[0];
|
|
484 | 460 |
} |
485 | 461 |
else |
486 | 462 |
{ |
487 |
tmp1 = vc.elementAt(vecCurr); |
|
488 |
buffer[offset ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx; |
|
489 |
buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy; |
|
463 |
buffer[offset ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0]; |
|
464 |
buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1]; |
|
490 | 465 |
} |
491 | 466 |
|
492 | 467 |
break; |
src/main/java/org/distorted/library/type/Dynamic3D.java | ||
---|---|---|
29 | 29 |
|
30 | 30 |
public class Dynamic3D extends Dynamic implements Data3D |
31 | 31 |
{ |
32 |
|
|
33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
34 |
// the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx etc. |
|
35 |
// (x,y,z) is the vector tangent to the path. |
|
36 |
// (vx,vy,vz) is the original vector from vv (copied here so when interpolating we can see if it is |
|
37 |
// still valid and if not - rebuild the Cache |
|
38 |
|
|
39 |
private class VectorCache |
|
40 |
{ |
|
41 |
float ax, bx, cx, dx; |
|
42 |
float ay, by, cy, dy; |
|
43 |
float az, bz, cz, dz; |
|
44 |
|
|
45 |
float x,y,z; |
|
46 |
float vx,vy,vz; |
|
47 |
} |
|
48 |
|
|
49 |
private Vector<VectorCache> vc; |
|
50 |
private VectorCache tmp1, tmp2; |
|
51 |
|
|
52 | 32 |
private Vector<Static3D> vv; |
53 | 33 |
private Static3D prev, curr, next; |
54 | 34 |
|
55 |
private float vec1X,vec1Y,vec1Z; // vector perpendicular to v(t) and in the same plane as v(t) and a(t) (for >2 points only, in case of 2 points this is calculated differently) |
|
56 |
private float vec2X,vec2Y,vec2Z; // vector perpendicular to v(t0 and to vec1. |
|
57 |
|
|
58 | 35 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
59 | 36 |
// no array bounds checking! |
60 | 37 |
|
... | ... | |
84 | 61 |
|
85 | 62 |
if( q>1 ) |
86 | 63 |
{ |
87 |
tmp1.x = nx+px/q;
|
|
88 |
tmp1.y = ny+py/q;
|
|
89 |
tmp1.z = nz+pz/q;
|
|
64 |
tmp1.tangent[0] = nx+px/q;
|
|
65 |
tmp1.tangent[1] = ny+py/q;
|
|
66 |
tmp1.tangent[2] = nz+pz/q;
|
|
90 | 67 |
} |
91 | 68 |
else |
92 | 69 |
{ |
93 |
tmp1.x = px+nx*q;
|
|
94 |
tmp1.y = py+ny*q;
|
|
95 |
tmp1.z = pz+nz*q;
|
|
70 |
tmp1.tangent[0] = px+nx*q;
|
|
71 |
tmp1.tangent[1] = py+ny*q;
|
|
72 |
tmp1.tangent[2] = pz+nz*q;
|
|
96 | 73 |
} |
97 | 74 |
} |
98 | 75 |
else |
99 | 76 |
{ |
100 |
tmp1.x = 0.0f;
|
|
101 |
tmp1.y = 0.0f;
|
|
102 |
tmp1.z = 0.0f;
|
|
77 |
tmp1.tangent[0] = 0.0f;
|
|
78 |
tmp1.tangent[1] = 0.0f;
|
|
79 |
tmp1.tangent[2] = 0.0f;
|
|
103 | 80 |
} |
104 | 81 |
} |
105 | 82 |
|
... | ... | |
112 | 89 |
tmp1= vc.elementAt(0); |
113 | 90 |
curr= vv.elementAt(0); |
114 | 91 |
|
115 |
tmp1.ax = tmp1.ay = tmp1.az = 0.0f;
|
|
116 |
tmp1.bx = tmp1.by = tmp1.bz = 0.0f;
|
|
117 |
tmp1.cx = curr.x;
|
|
118 |
tmp1.cy = curr.y;
|
|
119 |
tmp1.cz = curr.z;
|
|
120 |
tmp1.dx = tmp1.dy = tmp1.dz = 0.0f;
|
|
92 |
tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = 0.0f;
|
|
93 |
tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = 0.0f;
|
|
94 |
tmp1.c[0] = curr.x;
|
|
95 |
tmp1.c[1] = curr.y;
|
|
96 |
tmp1.c[2] = curr.z;
|
|
97 |
tmp1.d[0] = tmp1.d[1] = tmp1.d[2] = 0.0f;
|
|
121 | 98 |
} |
122 | 99 |
else if( numPoints==2 ) |
123 | 100 |
{ |
... | ... | |
126 | 103 |
curr= vv.elementAt(0); |
127 | 104 |
next= vv.elementAt(1); |
128 | 105 |
|
129 |
tmp1.ax = tmp1.ay = tmp1.az = 0.0f;
|
|
130 |
tmp1.bx = tmp1.by = tmp1.bz = 0.0f;
|
|
131 |
tmp1.cx = next.x - curr.x;
|
|
132 |
tmp1.cy = next.y - curr.y;
|
|
133 |
tmp1.cz = next.z - curr.z;
|
|
134 |
tmp1.dx = curr.x;
|
|
135 |
tmp1.dy = curr.y;
|
|
136 |
tmp1.dz = curr.z;
|
|
106 |
tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = 0.0f;
|
|
107 |
tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = 0.0f;
|
|
108 |
tmp1.c[0] = next.x - curr.x;
|
|
109 |
tmp1.c[1] = next.y - curr.y;
|
|
110 |
tmp1.c[2] = next.z - curr.z;
|
|
111 |
tmp1.d[0] = curr.x;
|
|
112 |
tmp1.d[1] = curr.y;
|
|
113 |
tmp1.d[2] = curr.z;
|
|
137 | 114 |
|
138 |
tmp2.ax = tmp2.ay = tmp2.az = 0.0f;
|
|
139 |
tmp2.bx = tmp2.by = tmp2.bz = 0.0f;
|
|
140 |
tmp2.cx = curr.x - next.x;
|
|
141 |
tmp2.cy = curr.y - next.y;
|
|
142 |
tmp2.cz = curr.z - next.z;
|
|
143 |
tmp2.dx = next.x;
|
|
144 |
tmp2.dy = next.y;
|
|
145 |
tmp2.dz = next.z;
|
|
115 |
tmp2.a[0] = tmp2.a[1] = tmp2.a[2] = 0.0f;
|
|
116 |
tmp2.b[0] = tmp2.b[1] = tmp2.b[2] = 0.0f;
|
|
117 |
tmp2.c[0] = curr.x - next.x;
|
|
118 |
tmp2.c[1] = curr.y - next.y;
|
|
119 |
tmp2.c[2] = curr.z - next.z;
|
|
120 |
tmp2.d[0] = next.x;
|
|
121 |
tmp2.d[1] = next.y;
|
|
122 |
tmp2.d[2] = next.z;
|
|
146 | 123 |
} |
147 | 124 |
else |
148 | 125 |
{ |
... | ... | |
159 | 136 |
curr= vv.elementAt(i); |
160 | 137 |
next= vv.elementAt(n); |
161 | 138 |
|
162 |
tmp1.vx = curr.x;
|
|
163 |
tmp1.vy = curr.y;
|
|
164 |
tmp1.vz = curr.z;
|
|
139 |
tmp1.cached[0] = curr.x;
|
|
140 |
tmp1.cached[1] = curr.y;
|
|
141 |
tmp1.cached[2] = curr.z;
|
|
165 | 142 |
|
166 |
tmp1.ax = 2*curr.x + tmp1.x - 2*next.x + tmp2.x;
|
|
167 |
tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
|
|
168 |
tmp1.cx = tmp1.x;
|
|
169 |
tmp1.dx = curr.x;
|
|
143 |
tmp1.a[0] = 2*curr.x + tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
|
|
144 |
tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
|
|
145 |
tmp1.c[0] = tmp1.tangent[0];
|
|
146 |
tmp1.d[0] = curr.x;
|
|
170 | 147 |
|
171 |
tmp1.ay = 2*curr.y + tmp1.y - 2*next.y + tmp2.y;
|
|
172 |
tmp1.by = -3*curr.y - 2*tmp1.y + 3*next.y - tmp2.y;
|
|
173 |
tmp1.cy = tmp1.y;
|
|
174 |
tmp1.dy = curr.y;
|
|
148 |
tmp1.a[1] = 2*curr.y + tmp1.tangent[1] - 2*next.y + tmp2.tangent[1];
|
|
149 |
tmp1.b[1] = -3*curr.y - 2*tmp1.tangent[1] + 3*next.y - tmp2.tangent[1];
|
|
150 |
tmp1.c[1] = tmp1.tangent[1];
|
|
151 |
tmp1.d[1] = curr.y;
|
|
175 | 152 |
|
176 |
tmp1.az = 2*curr.z + tmp1.z - 2*next.z + tmp2.z;
|
|
177 |
tmp1.bz = -3*curr.z - 2*tmp1.z + 3*next.z - tmp2.z;
|
|
178 |
tmp1.cz = tmp1.z;
|
|
179 |
tmp1.dz = curr.z;
|
|
153 |
tmp1.a[2] = 2*curr.z + tmp1.tangent[2] - 2*next.z + tmp2.tangent[2];
|
|
154 |
tmp1.b[2] = -3*curr.z - 2*tmp1.tangent[2] + 3*next.z - tmp2.tangent[2];
|
|
155 |
tmp1.c[2] = tmp1.tangent[2];
|
|
156 |
tmp1.d[2] = curr.z;
|
|
180 | 157 |
} |
181 | 158 |
} |
182 | 159 |
|
183 | 160 |
cacheDirty = false; |
184 | 161 |
} |
185 | 162 |
|
186 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
187 |
// v is the speed vector (i.e. position p(t) differentiated by time) |
|
188 |
// a is the acceleration vector (differentiate once more) |
|
189 |
// now what we are doing is compute vec1{X,Y,Z} to be a vector perpendicular to v and in the same plane as both v and a. |
|
190 |
// vec2{X,Y,Z} would be (v)x(vec1). |
|
191 |
// |
|
192 |
// vec1 = a-delta*v where delta = (v*a)/|v|^2 (see Gram-Schmidt) |
|
193 |
|
|
194 |
private void setUpVectors(float time,VectorCache vc) |
|
195 |
{ |
|
196 |
if( vc!=null ) |
|
197 |
{ |
|
198 |
float vx = (3*vc.ax*time+2*vc.bx)*time+vc.cx; |
|
199 |
float vy = (3*vc.ay*time+2*vc.by)*time+vc.cy; |
|
200 |
float vz = (3*vc.az*time+2*vc.bz)*time+vc.cz; |
|
201 |
|
|
202 |
float ax = 6*vc.ax*time+2*vc.bx; |
|
203 |
float ay = 6*vc.ay*time+2*vc.by; |
|
204 |
float az = 6*vc.az*time+2*vc.bz; |
|
205 |
|
|
206 |
float v_sq = vx*vx+vy*vy+vz*vz; |
|
207 |
float delta = (vx*ax+vy*ay+vz*az)/v_sq; |
|
208 |
|
|
209 |
vec1X = ax-delta*vx; |
|
210 |
vec1Y = ay-delta*vy; |
|
211 |
vec1Z = az-delta*vz; |
|
212 |
|
|
213 |
vec2X = vy*vec1Z-vz*vec1Y; |
|
214 |
vec2Y = vz*vec1X-vx*vec1Z; |
|
215 |
vec2Z = vx*vec1Y-vy*vec1X; |
|
216 |
|
|
217 |
float len1 = (float)Math.sqrt(v_sq/(vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z)); |
|
218 |
float len2 = (float)Math.sqrt(v_sq/(vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z)); |
|
219 |
|
|
220 |
vec1X*=len1; |
|
221 |
vec1Y*=len1; |
|
222 |
vec1Z*=len1; |
|
223 |
|
|
224 |
vec2X*=len2; |
|
225 |
vec2Y*=len2; |
|
226 |
vec2Z*=len2; |
|
227 |
} |
|
228 |
else |
|
229 |
{ |
|
230 |
curr = vv.elementAt(0); |
|
231 |
next = vv.elementAt(1); |
|
232 |
|
|
233 |
float vx = (next.x-curr.x); |
|
234 |
float vy = (next.y-curr.y); |
|
235 |
float vz = (next.z-curr.z); |
|
236 |
|
|
237 |
float b = (float)Math.sqrt(vx*vx+vy*vy); |
|
238 |
|
|
239 |
if( b>0.0f ) |
|
240 |
{ |
|
241 |
vec1X = vx*vz/b; |
|
242 |
vec1Y = vy*vz/b; |
|
243 |
vec1Z = -b; |
|
244 |
|
|
245 |
vec2X = vy*vec1Z-vz*vec1Y; |
|
246 |
vec2Y = vz*vec1X-vx*vec1Z; |
|
247 |
vec2Z = vx*vec1Y-vy*vec1X; |
|
248 |
|
|
249 |
float len2 = (float)Math.sqrt((vx*vx+vy*vy+vz*vz)/(vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z)); |
|
250 |
|
|
251 |
vec2X*=len2; |
|
252 |
vec2Y*=len2; |
|
253 |
vec2Z*=len2; |
|
254 |
} |
|
255 |
else |
|
256 |
{ |
|
257 |
vec1X = vz; |
|
258 |
vec1Y = 0.0f; |
|
259 |
vec1Z = 0.0f; |
|
260 |
|
|
261 |
vec2X = 0.0f; |
|
262 |
vec2Y = vz; |
|
263 |
vec2Z = 0.0f; |
|
264 |
} |
|
265 |
} |
|
266 |
} |
|
267 |
|
|
268 | 163 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
269 | 164 |
// PUBLIC API |
270 | 165 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
273 | 168 |
*/ |
274 | 169 |
public Dynamic3D() |
275 | 170 |
{ |
276 |
this(0,0.5f); |
|
171 |
super(0,0.5f,3); |
|
172 |
vv = new Vector<>(); |
|
277 | 173 |
} |
278 | 174 |
|
279 | 175 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
288 | 184 |
*/ |
289 | 185 |
public Dynamic3D(int duration, float count) |
290 | 186 |
{ |
187 |
super(duration,count,3); |
|
291 | 188 |
vv = new Vector<>(); |
292 |
vc = new Vector<>(); |
|
293 |
vn = null; |
|
294 |
numPoints = 0; |
|
295 |
cacheDirty = false; |
|
296 |
mMode = MODE_LOOP; |
|
297 |
mDuration = duration; |
|
298 |
mCount = count; |
|
299 |
mDimension = 3; |
|
300 | 189 |
} |
301 | 190 |
|
302 | 191 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
355 | 244 |
switch(numPoints) |
356 | 245 |
{ |
357 | 246 |
case 0: break; |
358 |
case 1: setUpVectors(0.0f,null);
|
|
247 |
case 1: computeOrthonormalBase2(vv.elementAt(0),v);
|
|
359 | 248 |
break; |
360 |
case 2: vc.add(new VectorCache()); |
|
361 |
vc.add(new VectorCache()); |
|
362 |
vc.add(new VectorCache()); |
|
249 |
case 2: vc.add(new VectorCache(3));
|
|
250 |
vc.add(new VectorCache(3));
|
|
251 |
vc.add(new VectorCache(3));
|
|
363 | 252 |
break; |
364 |
default:vc.add(new VectorCache()); |
|
253 |
default:vc.add(new VectorCache(3));
|
|
365 | 254 |
} |
366 | 255 |
|
367 | 256 |
numPoints++; |
... | ... | |
387 | 276 |
switch(numPoints) |
388 | 277 |
{ |
389 | 278 |
case 0: break; |
390 |
case 1: setUpVectors(0.0f,null);
|
|
279 |
case 1: computeOrthonormalBase2(vv.elementAt(0),v);
|
|
391 | 280 |
break; |
392 |
case 2: vc.add(new VectorCache()); |
|
393 |
vc.add(new VectorCache()); |
|
394 |
vc.add(new VectorCache()); |
|
281 |
case 2: vc.add(new VectorCache(3));
|
|
282 |
vc.add(new VectorCache(3));
|
|
283 |
vc.add(new VectorCache(3));
|
|
395 | 284 |
break; |
396 |
default:vc.add(location,new VectorCache()); |
|
285 |
default:vc.add(location,new VectorCache(3));
|
|
397 | 286 |
} |
398 | 287 |
|
399 | 288 |
numPoints++; |
... | ... | |
425 | 314 |
case 1: |
426 | 315 |
case 2: break; |
427 | 316 |
case 3: vc.removeAllElements(); |
428 |
setUpVectors(0.0f,null);
|
|
317 |
computeOrthonormalBase2(vv.elementAt(0),vv.elementAt(1));
|
|
429 | 318 |
break; |
430 | 319 |
default:vc.remove(n); |
431 | 320 |
} |
... | ... | |
464 | 353 |
case 1: |
465 | 354 |
case 2: break; |
466 | 355 |
case 3: vc.removeAllElements(); |
467 |
setUpVectors(0.0f,null);
|
|
356 |
computeOrthonormalBase2(vv.elementAt(0),vv.elementAt(1));
|
|
468 | 357 |
break; |
469 | 358 |
default:vc.removeElementAt(location); |
470 | 359 |
} |
... | ... | |
525 | 414 |
{ |
526 | 415 |
time = noise(time,0); |
527 | 416 |
|
528 |
buffer[offset ] = (next.x-curr.x)*time + curr.x + (vec1X*mFactor[0] + vec2X*mFactor[1]);
|
|
529 |
buffer[offset+1] = (next.y-curr.y)*time + curr.y + (vec1Y*mFactor[0] + vec2Y*mFactor[1]);
|
|
530 |
buffer[offset+2] = (next.z-curr.z)*time + curr.z + (vec1Z*mFactor[0] + vec2Z*mFactor[1]);
|
|
417 |
buffer[offset ] = (next.x-curr.x)*time + curr.x + (baseV[0][0]*mFactor[0] + baseV[1][0]*mFactor[1]);
|
|
418 |
buffer[offset+1] = (next.y-curr.y)*time + curr.y + (baseV[0][1]*mFactor[0] + baseV[1][1]*mFactor[1]);
|
|
419 |
buffer[offset+2] = (next.z-curr.z)*time + curr.z + (baseV[0][2]*mFactor[0] + baseV[1][2]*mFactor[1]);
|
|
531 | 420 |
} |
532 | 421 |
else |
533 | 422 |
{ |
... | ... | |
575 | 464 |
next = vv.elementAt(vecNext); |
576 | 465 |
tmp2 = vc.elementAt(vecNext); |
577 | 466 |
|
578 |
if( tmp2.vx!=next.x || tmp2.vy!=next.y || tmp2.vz!=next.z ) recomputeCache();
|
|
467 |
if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y || tmp2.cached[2]!=next.z ) recomputeCache();
|
|
579 | 468 |
} |
580 | 469 |
|
581 | 470 |
tmp1 = vc.elementAt(vecCurr); |
... | ... | |
584 | 473 |
{ |
585 | 474 |
time = noise(time,vecCurr); |
586 | 475 |
|
587 |
setUpVectors(time,tmp1);
|
|
476 |
computeOrthonormalBaseMore(time,tmp1);
|
|
588 | 477 |
|
589 |
buffer[offset ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx + (vec1X*mFactor[0] + vec2X*mFactor[1]);
|
|
590 |
buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy + (vec1Y*mFactor[0] + vec2Y*mFactor[1]);
|
|
591 |
buffer[offset+2]= ((tmp1.az*time+tmp1.bz)*time+tmp1.cz)*time+tmp1.dz + (vec1Z*mFactor[0] + vec2Z*mFactor[1]);
|
|
478 |
buffer[offset ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0] + (baseV[0][0]*mFactor[0] + baseV[1][0]*mFactor[1]);
|
|
479 |
buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1] + (baseV[0][1]*mFactor[0] + baseV[1][1]*mFactor[1]);
|
|
480 |
buffer[offset+2]= ((tmp1.a[2]*time+tmp1.b[2])*time+tmp1.c[2])*time+tmp1.d[2] + (baseV[0][2]*mFactor[0] + baseV[1][2]*mFactor[1]);
|
|
592 | 481 |
} |
593 | 482 |
else |
594 | 483 |
{ |
595 |
buffer[offset ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx;
|
|
596 |
buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy;
|
|
597 |
buffer[offset+2]= ((tmp1.az*time+tmp1.bz)*time+tmp1.cz)*time+tmp1.dz;
|
|
484 |
buffer[offset ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0];
|
|
485 |
buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1];
|
|
486 |
buffer[offset+2]= ((tmp1.a[2]*time+tmp1.b[2])*time+tmp1.c[2])*time+tmp1.d[2];
|
|
598 | 487 |
} |
599 | 488 |
|
600 | 489 |
break; |
src/main/java/org/distorted/library/type/Dynamic4D.java | ||
---|---|---|
29 | 29 |
|
30 | 30 |
public class Dynamic4D extends Dynamic implements Data4D |
31 | 31 |
{ |
32 |
|
|
33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
34 |
// the coefficients of the X(t), Y(t), Z(t), W(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx etc. |
|
35 |
// (x,y,z,w) is the vector tangent to the path. |
|
36 |
// (vx,vy,vz,vw) is the original vector from vv (copied here so when interpolating we can see if it is |
|
37 |
// still valid and if not - rebuild the Cache |
|
38 |
|
|
39 |
private class VectorCache |
|
40 |
{ |
|
41 |
float ax, bx, cx, dx; |
|
42 |
float ay, by, cy, dy; |
|
43 |
float az, bz, cz, dz; |
|
44 |
float aw, bw, cw, dw; |
|
45 |
|
|
46 |
float x,y,z,w; |
|
47 |
float vx,vy,vz,vw; |
|
48 |
} |
|
49 |
|
|
50 |
private Vector<VectorCache> vc; |
|
51 |
private VectorCache tmp1, tmp2; |
|
52 |
|
|
53 | 32 |
private Vector<Static4D> vv; |
54 | 33 |
private Static4D prev, curr, next; |
55 | 34 |
|
56 |
private float vec1X,vec1Y,vec1Z,vec1W; // vector perpendicular to v(t) and in the same plane as v(t) and a(t) (for >2 points only, in case of 2 points this is calculated differently) |
|
57 |
private float vec2X,vec2Y,vec2Z,vec2W; // vector perpendicular to v(t) and to vec1. |
|
58 |
private float vec3X,vec3Y,vec3Z,vec3W; // vector perpendicular to v(t) and to vec1. |
|
59 |
|
|
60 | 35 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
61 | 36 |
// no array bounds checking! |
62 | 37 |
|
... | ... | |
88 | 63 |
|
89 | 64 |
if( q>1 ) |
90 | 65 |
{ |
91 |
tmp1.x = nx+px/q;
|
|
92 |
tmp1.y = ny+py/q;
|
|
93 |
tmp1.z = nz+pz/q;
|
|
94 |
tmp1.w = nw+pw/q;
|
|
66 |
tmp1.tangent[0] = nx+px/q;
|
|
67 |
tmp1.tangent[1] = ny+py/q;
|
|
68 |
tmp1.tangent[2] = nz+pz/q;
|
|
69 |
tmp1.tangent[3] = nw+pw/q;
|
|
95 | 70 |
} |
96 | 71 |
else |
97 | 72 |
{ |
98 |
tmp1.x = px+nx*q;
|
|
99 |
tmp1.y = py+ny*q;
|
|
100 |
tmp1.z = pz+nz*q;
|
|
101 |
tmp1.w = pw+nw*q;
|
|
73 |
tmp1.tangent[0] = px+nx*q;
|
|
74 |
tmp1.tangent[1] = py+ny*q;
|
|
75 |
tmp1.tangent[2] = pz+nz*q;
|
|
76 |
tmp1.tangent[3] = pw+nw*q;
|
|
102 | 77 |
} |
103 | 78 |
} |
104 | 79 |
else |
105 | 80 |
{ |
106 |
tmp1.x = 0.0f;
|
|
107 |
tmp1.y = 0.0f;
|
|
108 |
tmp1.z = 0.0f;
|
|
109 |
tmp1.w = 0.0f;
|
|
81 |
tmp1.tangent[0] = 0.0f;
|
|
82 |
tmp1.tangent[1] = 0.0f;
|
|
83 |
tmp1.tangent[2] = 0.0f;
|
|
84 |
tmp1.tangent[3] = 0.0f;
|
|
110 | 85 |
} |
111 | 86 |
} |
112 | 87 |
|
... | ... | |
119 | 94 |
tmp1= vc.elementAt(0); |
120 | 95 |
curr= vv.elementAt(0); |
121 | 96 |
|
122 |
tmp1.ax = tmp1.ay = tmp1.az = tmp1.aw = 0.0f;
|
|
123 |
tmp1.bx = tmp1.by = tmp1.bz = tmp1.bw = 0.0f;
|
|
124 |
tmp1.cx = curr.x;
|
|
125 |
tmp1.cy = curr.y;
|
|
126 |
tmp1.cz = curr.z;
|
|
127 |
tmp1.cw = curr.w;
|
|
128 |
tmp1.dx = tmp1.dy = tmp1.dz = tmp1.dw = 0.0f;
|
|
97 |
tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = tmp1.a[3] = 0.0f;
|
|
98 |
tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = tmp1.b[3] = 0.0f;
|
|
99 |
tmp1.c[0] = curr.x;
|
|
100 |
tmp1.c[1] = curr.y;
|
|
101 |
tmp1.c[2] = curr.z;
|
|
102 |
tmp1.c[3] = curr.w;
|
|
103 |
tmp1.d[0] = tmp1.d[1] = tmp1.d[3] = tmp1.d[3] = 0.0f;
|
|
129 | 104 |
} |
130 | 105 |
else if( numPoints==2 ) |
131 | 106 |
{ |
... | ... | |
134 | 109 |
curr= vv.elementAt(0); |
135 | 110 |
next= vv.elementAt(1); |
136 | 111 |
|
137 |
tmp1.ax = tmp1.ay = tmp1.az = tmp1.aw = 0.0f;
|
|
138 |
tmp1.bx = tmp1.by = tmp1.bz = tmp1.bw = 0.0f;
|
|
139 |
tmp1.cx = next.x - curr.x;
|
|
140 |
tmp1.cy = next.y - curr.y;
|
|
141 |
tmp1.cz = next.z - curr.z;
|
|
142 |
tmp1.cw = next.w - curr.w;
|
|
143 |
tmp1.dx = curr.x;
|
|
144 |
tmp1.dy = curr.y;
|
|
145 |
tmp1.dz = curr.z;
|
|
146 |
tmp1.dw = curr.w;
|
|
112 |
tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = tmp1.a[3] = 0.0f;
|
|
113 |
tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = tmp1.b[3] = 0.0f;
|
|
114 |
tmp1.c[0] = next.x - curr.x;
|
|
115 |
tmp1.c[1] = next.y - curr.y;
|
|
116 |
tmp1.c[2] = next.z - curr.z;
|
|
117 |
tmp1.c[3] = next.w - curr.w;
|
|
118 |
tmp1.d[0] = curr.x;
|
|
119 |
tmp1.d[1] = curr.y;
|
|
120 |
tmp1.d[2] = curr.z;
|
|
121 |
tmp1.d[3] = curr.w;
|
|
147 | 122 |
|
148 |
tmp2.ax = tmp2.ay = tmp2.az = tmp2.aw = 0.0f;
|
|
149 |
tmp2.bx = tmp2.by = tmp2.bz = tmp2.bw = 0.0f;
|
|
150 |
tmp2.cx = curr.x - next.x;
|
|
151 |
tmp2.cy = curr.y - next.y;
|
|
152 |
tmp2.cz = curr.z - next.z;
|
|
153 |
tmp2.cw = curr.w - next.w;
|
|
154 |
tmp2.dx = next.x;
|
|
155 |
tmp2.dy = next.y;
|
|
156 |
tmp2.dz = next.z;
|
|
157 |
tmp2.dw = next.w;
|
|
123 |
tmp2.a[0] = tmp2.a[1] = tmp2.a[2] = tmp2.a[3] = 0.0f;
|
|
124 |
tmp2.b[0] = tmp2.b[1] = tmp2.b[2] = tmp2.b[3] = 0.0f;
|
|
125 |
tmp2.c[0] = curr.x - next.x;
|
|
126 |
tmp2.c[1] = curr.y - next.y;
|
|
127 |
tmp2.c[2] = curr.z - next.z;
|
|
128 |
tmp2.c[3] = curr.w - next.w;
|
|
129 |
tmp2.d[0] = next.x;
|
|
130 |
tmp2.d[1] = next.y;
|
|
131 |
tmp2.d[2] = next.z;
|
|
132 |
tmp2.d[3] = next.w;
|
|
158 | 133 |
} |
159 | 134 |
else |
160 | 135 |
{ |
... | ... | |
171 | 146 |
curr= vv.elementAt(i); |
172 | 147 |
next= vv.elementAt(n); |
173 | 148 |
|
174 |
tmp1.vx = curr.x;
|
|
175 |
tmp1.vy = curr.y;
|
|
176 |
tmp1.vz = curr.z;
|
|
177 |
tmp1.vw = curr.w;
|
|
149 |
tmp1.cached[0] = curr.x;
|
|
150 |
tmp1.cached[1] = curr.y;
|
|
151 |
tmp1.cached[2] = curr.z;
|
|
152 |
tmp1.cached[3] = curr.w;
|
|
178 | 153 |
|
179 |
tmp1.ax = 2*curr.x + tmp1.x - 2*next.x + tmp2.x;
|
|
180 |
tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
|
|
181 |
tmp1.cx = tmp1.x;
|
|
182 |
tmp1.dx = curr.x;
|
|
154 |
tmp1.a[0] = 2*curr.x + tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
|
|
155 |
tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
|
|
156 |
tmp1.c[0] = tmp1.tangent[0];
|
|
157 |
tmp1.d[0] = curr.x;
|
|
183 | 158 |
|
184 |
tmp1.ay = 2*curr.y + tmp1.y - 2*next.y + tmp2.y;
|
|
185 |
tmp1.by = -3*curr.y - 2*tmp1.y + 3*next.y - tmp2.y;
|
|
186 |
tmp1.cy = tmp1.y;
|
|
187 |
tmp1.dy = curr.y;
|
|
159 |
tmp1.a[1] = 2*curr.y + tmp1.tangent[1] - 2*next.y + tmp2.tangent[1];
|
|
160 |
tmp1.b[1] = -3*curr.y - 2*tmp1.tangent[1] + 3*next.y - tmp2.tangent[1];
|
|
161 |
tmp1.c[1] = tmp1.tangent[1];
|
|
162 |
tmp1.d[1] = curr.y;
|
|
188 | 163 |
|
189 |
tmp1.az = 2*curr.z + tmp1.z - 2*next.z + tmp2.z;
|
|
190 |
tmp1.bz = -3*curr.z - 2*tmp1.z + 3*next.z - tmp2.z;
|
|
191 |
tmp1.cz = tmp1.z;
|
|
192 |
tmp1.dz = curr.z;
|
|
164 |
tmp1.a[2] = 2*curr.z + tmp1.tangent[2] - 2*next.z + tmp2.tangent[2];
|
|
165 |
tmp1.b[2] = -3*curr.z - 2*tmp1.tangent[2] + 3*next.z - tmp2.tangent[2];
|
|
166 |
tmp1.c[2] = tmp1.tangent[2];
|
|
167 |
tmp1.d[2] = curr.z;
|
|
193 | 168 |
|
194 |
tmp1.aw = 2*curr.w + tmp1.w - 2*next.w + tmp2.w;
|
|
195 |
tmp1.bw = -3*curr.w - 2*tmp1.w + 3*next.w - tmp2.w;
|
|
196 |
tmp1.cw = tmp1.w;
|
|
197 |
tmp1.dw = curr.w;
|
|
169 |
tmp1.a[3] = 2*curr.w + tmp1.tangent[3] - 2*next.w + tmp2.tangent[3];
|
|
170 |
tmp1.b[3] = -3*curr.w - 2*tmp1.tangent[3] + 3*next.w - tmp2.tangent[3];
|
|
171 |
tmp1.c[3] = tmp1.tangent[3];
|
|
172 |
tmp1.d[3] = curr.w;
|
|
198 | 173 |
} |
199 | 174 |
} |
200 | 175 |
|
201 | 176 |
cacheDirty = false; |
202 | 177 |
} |
203 | 178 |
|
204 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
205 |
// v is the speed vector (i.e. position p(t) differentiated by time) |
|
206 |
// a is the acceleration vector (differentiate once more) |
|
207 |
// |
|
208 |
// Now we construct orthogonal basis with Gram-Schmidt: |
|
209 |
// vec1 = a-delta*v where delta = (v*a)/|v|^2 |
|
210 |
// vec2 = (0,0,1,0) - coeff1*(vx,vy,vz,vw) - coeff2*(vec1x,vec1y,vec1z,vec1w) where coeff1 = vz/|v|^2, coeff2 = vec1Z/|vec1|^2 |
|
211 |
// vec3 = (0,0,0,1) - coeff1*(vx,vy,vz,vw) - coeff2*(vec1x,vec1y,vec1z,vec1w) - coeff3*(vec2x,vec2y,vec2z,vec2w) where coeff1 = vw/|v|^2, coeff2 = vec1W/|vec1|^2, coeff3 = vec2W/|vec2|^2 |
|
212 |
|
|
213 |
private void setUpVectors(float time,VectorCache vc) |
|
214 |
{ |
|
215 |
if( vc!=null ) |
|
216 |
{ |
|
217 |
float vx = (3*vc.ax*time+2*vc.bx)*time+vc.cx; |
|
218 |
float vy = (3*vc.ay*time+2*vc.by)*time+vc.cy; |
|
219 |
float vz = (3*vc.az*time+2*vc.bz)*time+vc.cz; |
|
220 |
float vw = (3*vc.aw*time+2*vc.bw)*time+vc.cw; |
|
221 |
|
|
222 |
float ax = 6*vc.ax*time+2*vc.bx; |
|
223 |
float ay = 6*vc.ay*time+2*vc.by; |
|
224 |
float az = 6*vc.az*time+2*vc.bz; |
|
225 |
float aw = 6*vc.aw*time+2*vc.bw; |
|
226 |
|
|
227 |
float v_sq = vx*vx+vy*vy+vz*vz+vw*vw; |
|
228 |
float delta = (vx*ax+vy*ay+vz*az+vw*aw)/v_sq; |
|
229 |
|
|
230 |
vec1X = ax-delta*vx; |
|
231 |
vec1Y = ay-delta*vy; |
|
232 |
vec1Z = az-delta*vz; |
|
233 |
vec1W = aw-delta*vw; |
|
234 |
|
|
235 |
float vec1_sq = vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z+vec1W*vec1W; |
|
236 |
|
|
237 |
// construct vec2 and vec3. Cross product does not work in 4th dimension! |
|
238 |
float coeff21 = vz/v_sq; |
|
239 |
float coeff22 = vec1Z/vec1_sq; |
|
240 |
vec2X = 0.0f - coeff21*vx - coeff22*vec1X; |
|
241 |
vec2Y = 0.0f - coeff21*vy - coeff22*vec1Y; |
|
242 |
vec2Z = 1.0f - coeff21*vz - coeff22*vec1Z; |
|
243 |
vec2W = 0.0f - coeff21*vw - coeff22*vec1W; |
|
244 |
|
|
245 |
float vec2_sq = vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z+vec2W*vec2W; |
|
246 |
float coeff31 = vw/v_sq; |
|
247 |
float coeff32 = vec1W/vec1_sq; |
|
248 |
float coeff33 = vec2W/vec2_sq; |
|
249 |
vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X; |
|
250 |
vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y; |
|
251 |
vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z; |
|
252 |
vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W; |
|
253 |
|
|
254 |
float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W; |
|
255 |
|
|
256 |
float len1 = (float)Math.sqrt(v_sq/vec1_sq); |
|
257 |
float len2 = (float)Math.sqrt(v_sq/vec2_sq); |
|
258 |
float len3 = (float)Math.sqrt(v_sq/vec3_sq); |
|
259 |
|
|
260 |
vec1X*=len1; |
|
261 |
vec1Y*=len1; |
|
262 |
vec1Z*=len1; |
|
263 |
vec1W*=len1; |
|
264 |
|
|
265 |
vec2X*=len2; |
|
266 |
vec2Y*=len2; |
|
267 |
vec2Z*=len2; |
|
268 |
vec2W*=len2; |
|
269 |
|
|
270 |
vec3X*=len3; |
|
271 |
vec3Y*=len3; |
|
272 |
vec3Z*=len3; |
|
273 |
vec3W*=len3; |
|
274 |
} |
|
275 |
else |
|
276 |
{ |
|
277 |
curr = vv.elementAt(0); |
|
278 |
next = vv.elementAt(1); |
|
279 |
|
|
280 |
float vx = (next.x-curr.x); |
|
281 |
float vy = (next.y-curr.y); |
|
282 |
float vz = (next.z-curr.z); |
|
283 |
float vw = (next.w-curr.w); |
|
284 |
|
|
285 |
float b = (float)Math.sqrt(vx*vx+vy*vy+vz*vz); |
|
286 |
|
|
287 |
if( b>0.0f ) |
|
288 |
{ |
|
289 |
vec1X = vx*vw/b; |
|
290 |
vec1Y = vy*vw/b; |
|
291 |
vec1Z = vz*vw/b; |
|
292 |
vec1W = -b; |
|
293 |
|
|
294 |
float v_sq = vx*vx+vy*vy+vz*vz+vw*vw; |
|
295 |
float vec1_sq = vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z+vec1W*vec1W; |
|
296 |
|
|
297 |
// construct vec2 and vec3. Cross product does not work in 4th dimension! |
|
298 |
float coeff21 = vz/v_sq; |
|
299 |
float coeff22 = vec1Z/vec1_sq; |
|
300 |
vec2X = 0.0f - coeff21*vx - coeff22*vec1X; |
|
301 |
vec2Y = 0.0f - coeff21*vy - coeff22*vec1Y; |
|
302 |
vec2Z = 1.0f - coeff21*vz - coeff22*vec1Z; |
|
303 |
vec2W = 0.0f - coeff21*vw - coeff22*vec1W; |
|
304 |
|
|
305 |
float vec2_sq = vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z+vec2W*vec2W; |
|
306 |
float coeff31 = vw/v_sq; |
|
307 |
float coeff32 = vec1W/vec1_sq; |
|
308 |
float coeff33 = vec2W/vec2_sq; |
|
309 |
vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X; |
|
310 |
vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y; |
|
311 |
vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z; |
|
312 |
vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W; |
|
313 |
|
|
314 |
float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W; |
|
315 |
|
|
316 |
float len1 = (float)Math.sqrt(v_sq/vec1_sq); |
|
317 |
float len2 = (float)Math.sqrt(v_sq/vec2_sq); |
|
318 |
float len3 = (float)Math.sqrt(v_sq/vec3_sq); |
|
319 |
|
|
320 |
vec1X*=len1; |
|
321 |
vec1Y*=len1; |
|
322 |
vec1Z*=len1; |
|
323 |
vec1W*=len1; |
|
324 |
|
|
325 |
vec2X*=len2; |
|
326 |
vec2Y*=len2; |
|
327 |
vec2Z*=len2; |
|
328 |
vec2W*=len2; |
|
329 |
|
|
330 |
vec3X*=len3; |
|
331 |
vec3Y*=len3; |
|
332 |
vec3Z*=len3; |
|
333 |
vec3W*=len3; |
|
334 |
} |
|
335 |
else |
|
336 |
{ |
|
337 |
vec1X = vw; |
|
338 |
vec1Y = 0.0f; |
|
339 |
vec1Z = 0.0f; |
|
340 |
vec1W = 0.0f; |
|
341 |
|
|
342 |
vec2X = 0.0f; |
|
343 |
vec2Y = vw; |
|
344 |
vec2Z = 0.0f; |
|
345 |
vec2W = 0.0f; |
|
346 |
|
|
347 |
vec3X = 0.0f; |
|
348 |
vec3Y = 0.0f; |
|
349 |
vec3Z = vw; |
|
350 |
vec3W = 0.0f; |
|
351 |
} |
|
352 |
} |
|
353 |
} |
|
354 |
|
|
355 | 179 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
356 | 180 |
// PUBLIC API |
357 | 181 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
Also available in: Unified diff
Completely redesign Noise in the Dynamics and move all the complexity to the parent class.
something does not work with it now :)