Revision 649544b8
Added by Leszek Koltunski over 7 years ago
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; |
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 :)