Project

General

Profile

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

library / src / main / java / org / distorted / library / type / Dynamic5D.java @ 8c57d77b

1
////////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

    
21
package org.distorted.library.type;
22

    
23
import java.util.Vector;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
/** 
27
* A 5-dimensional implementation of the Dynamic class to interpolate between a list
28
* of Static5Ds.
29
*/
30

    
31
public class Dynamic5D extends Dynamic implements Data5D
32
  {
33
  private Vector<Static5D> vv;
34
  private Static5D prev, curr, next;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37
// no array bounds checking!
38
  
39
  private void computeVelocity(int c)
40
    {
41
    int p = c>0 ? c-1: numPoints-1;
42
    int n = c<numPoints-1 ? c+1: 0;
43
    
44
    prev = vv.elementAt(p);
45
    curr = vv.elementAt(c);
46
    next = vv.elementAt(n);
47

    
48
    tmpCache1 = vc.elementAt(c);
49
    
50
    float px = curr.x - prev.x;
51
    float py = curr.y - prev.y;
52
    float pz = curr.z - prev.z;
53
    float pw = curr.w - prev.w;
54
    float pv = curr.v - prev.v;
55
    float nx = next.x - curr.x;
56
    float ny = next.y - curr.y;
57
    float nz = next.z - curr.z;
58
    float nw = next.w - curr.w;
59
    float nv = next.v - curr.v;
60
     
61
    float d = nx*nx+ny*ny+nz*nz+nw*nw+nv*nv;
62
    
63
    if( d>0 )
64
      {
65
      float q = (float)Math.sqrt((px*px+py*py+pz*pz+pw*pw+pv*pv)/d);
66
      
67
      if( q>1 )
68
        {
69
        tmpCache1.velocity[0] = nx+px/q;
70
        tmpCache1.velocity[1] = ny+py/q;
71
        tmpCache1.velocity[2] = nz+pz/q;
72
        tmpCache1.velocity[3] = nw+pw/q;
73
        tmpCache1.velocity[4] = nv+pv/q;
74
        }
75
      else
76
        {
77
        tmpCache1.velocity[0] = px+nx*q;
78
        tmpCache1.velocity[1] = py+ny*q;
79
        tmpCache1.velocity[2] = pz+nz*q;
80
        tmpCache1.velocity[3] = pw+nw*q;
81
        tmpCache1.velocity[4] = pv+nv*q;
82
        }
83
      }
84
    else
85
      {
86
      tmpCache1.velocity[0] = 0.0f;
87
      tmpCache1.velocity[1] = 0.0f;
88
      tmpCache1.velocity[2] = 0.0f;
89
      tmpCache1.velocity[3] = 0.0f;
90
      tmpCache1.velocity[4] = 0.0f;
91
      }
92
    }
93
    
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95
  
96
  private void recomputeCache()
97
    {  
98
    if( numPoints==1 )
99
      {
100
      tmpCache1 = vc.elementAt(0);
101
      curr= vv.elementAt(0);
102
        
103
      tmpCache1.a[0] = tmpCache1.a[1] = tmpCache1.a[2] = tmpCache1.a[3] = tmpCache1.a[4] = 0.0f;
104
      tmpCache1.b[0] = tmpCache1.b[1] = tmpCache1.b[2] = tmpCache1.b[3] = tmpCache1.b[4] = 0.0f;
105
      tmpCache1.c[0] = curr.x;
106
      tmpCache1.c[1] = curr.y;
107
      tmpCache1.c[2] = curr.z;
108
      tmpCache1.c[3] = curr.w;
109
      tmpCache1.c[4] = curr.v;
110
      tmpCache1.d[0] = tmpCache1.d[1] = tmpCache1.d[2] = tmpCache1.d[3] = tmpCache1.d[4] = 0.0f;
111
      }
112
    else if( numPoints==2 )
113
      {
114
      tmpCache1 = vc.elementAt(0);
115
      tmpCache2 = vc.elementAt(1);
116
      curr= vv.elementAt(0);
117
      next= vv.elementAt(1);
118
      
119
      tmpCache1.a[0] = tmpCache1.a[1] = tmpCache1.a[2] = tmpCache1.a[3] = tmpCache1.a[4] = 0.0f;
120
      tmpCache1.b[0] = tmpCache1.b[1] = tmpCache1.b[2] = tmpCache1.b[3] = tmpCache1.b[4] = 0.0f;
121
      tmpCache1.c[0] = next.x - curr.x;
122
      tmpCache1.c[1] = next.y - curr.y;
123
      tmpCache1.c[2] = next.z - curr.z;
124
      tmpCache1.c[3] = next.w - curr.w;
125
      tmpCache1.c[4] = next.v - curr.v;
126
      tmpCache1.d[0] = curr.x;
127
      tmpCache1.d[1] = curr.y;
128
      tmpCache1.d[2] = curr.z;
129
      tmpCache1.d[3] = curr.w;
130
      tmpCache1.d[4] = curr.v;
131
      
132
      tmpCache2.a[0] = tmpCache2.a[1] = tmpCache2.a[2] = tmpCache2.a[3] = tmpCache2.a[4] = 0.0f;
133
      tmpCache2.b[0] = tmpCache2.b[1] = tmpCache2.b[2] = tmpCache2.b[3] = tmpCache2.b[4] = 0.0f;
134
      tmpCache2.c[0] = curr.x - next.x;
135
      tmpCache2.c[1] = curr.y - next.y;
136
      tmpCache2.c[2] = curr.z - next.z;
137
      tmpCache2.c[3] = curr.w - next.w;
138
      tmpCache2.c[4] = curr.v - next.v;
139
      tmpCache2.d[0] = next.x;
140
      tmpCache2.d[1] = next.y;
141
      tmpCache2.d[2] = next.z;
142
      tmpCache2.d[3] = next.w;
143
      tmpCache2.d[4] = next.v;
144
      }
145
    else
146
      {
147
      int i, n;  
148
      
149
      for(i=0; i<numPoints; i++) computeVelocity(i);
150
   
151
      for(i=0; i<numPoints; i++)
152
        {
153
        n = i<numPoints-1 ? i+1:0;  
154
      
155
        tmpCache1 = vc.elementAt(i);
156
        tmpCache2 = vc.elementAt(n);
157
        curr= vv.elementAt(i);
158
        next= vv.elementAt(n);
159
      
160
        tmpCache1.cached[0] = curr.x;
161
        tmpCache1.cached[1] = curr.y;
162
        tmpCache1.cached[2] = curr.z;
163
        tmpCache1.cached[3] = curr.w;
164
        tmpCache1.cached[4] = curr.v;
165
        
166
        tmpCache1.a[0] = mConvexity*( 2*curr.x +   tmpCache1.velocity[0] - 2*next.x + tmpCache2.velocity[0]);
167
        tmpCache1.b[0] = mConvexity*(-3*curr.x - 2* tmpCache1.velocity[0] + 3*next.x - tmpCache2.velocity[0]);
168
        tmpCache1.c[0] = mConvexity*(tmpCache1.velocity[0]) + (1.0f-mConvexity)*(next.x-curr.x);
169
        tmpCache1.d[0] = curr.x;
170
      
171
        tmpCache1.a[1] = mConvexity*( 2*curr.y +   tmpCache1.velocity[1] - 2*next.y + tmpCache2.velocity[1]);
172
        tmpCache1.b[1] = mConvexity*(-3*curr.y - 2* tmpCache1.velocity[1] + 3*next.y - tmpCache2.velocity[1]);
173
        tmpCache1.c[1] = mConvexity*(tmpCache1.velocity[1]) + (1.0f-mConvexity)*(next.y-curr.y);
174
        tmpCache1.d[1] = curr.y;
175
      
176
        tmpCache1.a[2] = mConvexity*( 2*curr.z +   tmpCache1.velocity[2] - 2*next.z + tmpCache2.velocity[2]);
177
        tmpCache1.b[2] = mConvexity*(-3*curr.z - 2* tmpCache1.velocity[2] + 3*next.z - tmpCache2.velocity[2]);
178
        tmpCache1.c[2] = mConvexity*(tmpCache1.velocity[2]) + (1.0f-mConvexity)*(next.z-curr.z);
179
        tmpCache1.d[2] = curr.z;
180
        
181
        tmpCache1.a[3] = mConvexity*( 2*curr.w +   tmpCache1.velocity[3] - 2*next.w + tmpCache2.velocity[3]);
182
        tmpCache1.b[3] = mConvexity*(-3*curr.w - 2* tmpCache1.velocity[3] + 3*next.w - tmpCache2.velocity[3]);
183
        tmpCache1.c[3] = mConvexity*(tmpCache1.velocity[3]) + (1.0f-mConvexity)*(next.w-curr.w);
184
        tmpCache1.d[3] = curr.w;
185
        
186
        tmpCache1.a[4] = mConvexity*( 2*curr.v +   tmpCache1.velocity[4] - 2*next.v + tmpCache2.velocity[4]);
187
        tmpCache1.b[4] = mConvexity*(-3*curr.v - 2* tmpCache1.velocity[4] + 3*next.v - tmpCache2.velocity[4]);
188
        tmpCache1.c[4] = mConvexity*(tmpCache1.velocity[4]) + (1.0f-mConvexity)*(next.v-curr.v);
189
        tmpCache1.d[4] = curr.v;
190

    
191
        if( mSpeedMode==SPEED_MODE_SEGMENT_CONSTANT ) smoothOutSegment(tmpCache1);
192
        }
193
      }
194
   
195
    cacheDirty = false;
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199
// PUBLIC API
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201
/**
202
 * Default constructor.
203
 */
204
  public Dynamic5D()
205
    {
206
    super(0,0.5f,5);
207
    vv = new Vector<>();
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211
/**
212
 * Constructor setting the speed of interpolation and the number of revolutions.
213
 *
214
 * What constitutes 'one revolution' depends on the MODE:
215
 * {@link Dynamic#MODE_LOOP}, {@link Dynamic#MODE_PATH} or {@link Dynamic#MODE_JUMP}.
216
 *
217
 * @param duration number of milliseconds it takes to do one revolution.
218
 * @param count    number of revolutions we will do. Count<=0 means 'infinite'.
219
 */
220
  public Dynamic5D(int duration, float count)
221
    {
222
    super(duration,count,5);
223
    vv = new Vector<>();
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
/**
228
 * Returns the location'th Static5D.
229
 *   
230
 * @param location the index of the Point we are interested in.
231
 * @return The Static5D, if 0<=location&lt;getNumPoints(), or null otherwise.
232
 */  
233
  public synchronized Static5D getPoint(int location)
234
    {
235
    return (location>=0 && location<numPoints) ? vv.elementAt(location) : null;  
236
    }
237
  
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239
/**
240
 * Resets the location'th Point.
241
 * 
242
 * @param location the index of the Point we are setting.
243
 * @param x New value of its first float.
244
 */
245
  public synchronized void setPoint(int location, float x, float y, float z, float w, float v)
246
    {
247
    if( location>=0 && location<numPoints )
248
      {
249
      curr = vv.elementAt(location);
250
   
251
      if( curr!=null )
252
        {
253
        curr.set(x,y,z,w,v);
254
        cacheDirty=true;
255
        }
256
      }
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260
/**
261
 * Adds a new Static5D to the end of our list of Points to interpolate through.
262
 * <p>   
263
 * Only a reference to the Point gets added to the List; this means that one can add a Point 
264
 * here, and later on {@link Static5D#set(float,float,float,float,float)} it to some new value and
265
 * the change will be seamlessly reflected in the interpolated path.  
266
 * <p>
267
 * A Point can be added multiple times.
268
 *   
269
 * @param v The Point to add.
270
 */    
271
  public synchronized void add(Static5D v)
272
    {
273
    if( v!=null )
274
      {
275
      vv.add(v);
276
        
277
      if( vn!=null ) vn.add(new VectorNoise());
278
       
279
      switch(numPoints)
280
        {
281
        case 0: break;
282
        case 1: computeOrthonormalBase2(vv.elementAt(0),v);
283
                break;
284
        case 2: vc.add(new VectorCache());
285
                vc.add(new VectorCache());
286
                vc.add(new VectorCache());
287
                break;
288
        default:vc.add(new VectorCache());
289
        }
290

    
291
      numPoints++;
292
      cacheDirty = true;
293
      }
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297
/**
298
 * Adds a new Static5D to the location'th place in our List of Points to interpolate through.
299
 *   
300
 * @param location Index in our List to add the new Point at.
301
 * @param v The Static5D to add.
302
 */  
303
  public synchronized void add(int location, Static5D v)
304
    {
305
    if( v!=null )
306
      {
307
      vv.add(location, v);
308
      
309
      if( vn!=null ) vn.add(new VectorNoise());
310
      
311
      switch(numPoints)
312
        {
313
        case 0: break;
314
        case 1: computeOrthonormalBase2(vv.elementAt(0),v);
315
                break;
316
        case 2: vc.add(new VectorCache());
317
                vc.add(new VectorCache());
318
                vc.add(new VectorCache());
319
                break;
320
        default:vc.add(location,new VectorCache());
321
        }
322

    
323
      numPoints++;
324
      cacheDirty = true;
325
      }
326
    }
327
  
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329
/**
330
 * Removes all occurrences of Point v from the List of Points to interpolate through.  
331
 * 
332
 * @param v The Point to remove.
333
 * @return <code>true</code> if we have removed at least one Point.
334
 */
335
  public synchronized boolean remove(Static5D v)
336
    {
337
    int n = vv.indexOf(v);
338
    boolean found = false;
339
   
340
    while( n>=0 ) 
341
      {
342
      vv.remove(n);
343
     
344
      if( vn!=null ) vn.remove(0);
345
     
346
      switch(numPoints)
347
        {
348
        case 0:
349
        case 1: 
350
        case 2: break;
351
        case 3: vc.removeAllElements();
352
                computeOrthonormalBase2(vv.elementAt(0),vv.elementAt(1));
353
                break;
354
        default:vc.remove(n);
355
        }
356

    
357
      numPoints--;
358
      found = true;
359
      n = vv.indexOf(v);
360
      }
361
   
362
    if( found ) 
363
      {
364
      cacheDirty=true;
365
      }
366
   
367
    return found;
368
    }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371
/**
372
 * Removes a location'th Point from the List of Points we interpolate through.
373
 * 
374
 * @param location index of the Point we want to remove. 
375
 * @return <code>true</code> if location is valid, i.e. if 0<=location&lt;getNumPoints().
376
 */
377
  public synchronized boolean remove(int location)
378
    {
379
    if( location>=0 && location<numPoints ) 
380
      {
381
      vv.removeElementAt(location);
382
       
383
      if( vn!=null ) vn.remove(0);
384
      
385
      switch(numPoints)
386
        {
387
        case 0:
388
        case 1: 
389
        case 2: break;
390
        case 3: vc.removeAllElements();
391
                computeOrthonormalBase2(vv.elementAt(0),vv.elementAt(1));
392
                break;
393
        default:vc.removeElementAt(location);
394
        }
395

    
396
      numPoints--;
397
      cacheDirty = true; 
398
      return true;
399
      }
400

    
401
    return false;
402
    }
403
  
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405
/**
406
 * Removes all Points.
407
 */
408
  public synchronized void removeAll()
409
    {
410
    numPoints = 0;
411
    vv.removeAllElements();
412
    vc.removeAllElements();
413
    cacheDirty = false;
414
   
415
    if( vn!=null ) vn.removeAllElements();
416
    }
417

    
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419
/**
420
 * Sets the 'smoothness' of interpolation.
421
 * <p>
422
 * When Noise=0 (the default), we interpolate between our Points through the most smooth path possible.
423
 * Increasing noise makes the Dynamic increasingly deviate from this path, pseudo-randomly speeding
424
 * up and slowing down, etc.
425
 *
426
 * @param noise The noise level. Permitted range: 0 <= noise <= 1.
427
 */
428

    
429
  public synchronized void setNoise(Static5D noise)
430
    {
431
    if( vn==null )
432
      {
433
      vn = new Vector<>();
434
      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise());
435

    
436
      if( mDimension>=2 )
437
        {
438
        mFactor = new float[mDimension-1];
439
        }
440

    
441
      mNoise = new float[mDimension];
442
      }
443

    
444
    if( noise.x<0.0f ) noise.x = 0.0f;
445
    if( noise.x>1.0f ) noise.x = 1.0f;
446
    if( noise.y<0.0f ) noise.y = 0.0f;
447
    if( noise.y>1.0f ) noise.y = 1.0f;
448
    if( noise.z<0.0f ) noise.z = 0.0f;
449
    if( noise.z>1.0f ) noise.z = 1.0f;
450
    if( noise.w<0.0f ) noise.w = 0.0f;
451
    if( noise.w>1.0f ) noise.w = 1.0f;
452
    if( noise.v<0.0f ) noise.v = 0.0f;
453
    if( noise.v>1.0f ) noise.v = 1.0f;
454

    
455
    mNoise[0] = noise.x;
456
    mNoise[1] = noise.y;
457
    mNoise[2] = noise.z;
458
    mNoise[3] = noise.w;
459
    mNoise[4] = noise.v;
460
    }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

    
464
  synchronized void interpolate(float[] buffer, int offset, float time)
465
    {  
466
    switch(numPoints)
467
      {
468
      case 0: buffer[offset  ] = 0.0f;
469
              buffer[offset+1] = 0.0f;
470
              buffer[offset+2] = 0.0f;
471
              buffer[offset+3] = 0.0f;
472
              buffer[offset+4] = 0.0f;
473
              break;
474
      case 1: curr = vv.elementAt(0);
475
              buffer[offset  ] = curr.x;
476
              buffer[offset+1] = curr.y;
477
              buffer[offset+2] = curr.z;
478
              buffer[offset+3] = curr.w;
479
              buffer[offset+4] = curr.v;
480
              break;
481
      case 2: curr = vv.elementAt(0);
482
              next = vv.elementAt(1);
483

    
484
              int segment= (int)(2*time);
485

    
486
              if( mMode==MODE_LOOP || mMode==MODE_PATH ) time = (time>0.5f ? 2-2*time : 2*time);
487

    
488
              if( vn!=null )
489
                {
490
                if( segment != mSegment )
491
                  {
492
                  if(mMode!=MODE_JUMP || mSegment==1) vn.elementAt(0).computeNoise();
493
                  mSegment = segment;
494
                  }
495

    
496
                time = noise(time,0);
497

    
498
                buffer[offset  ] = (next.x-curr.x)*time + curr.x + (baseV[1][0]*mFactor[0] + baseV[2][0]*mFactor[1] + baseV[3][0]*mFactor[2] + baseV[4][0]*mFactor[3]);
499
                buffer[offset+1] = (next.y-curr.y)*time + curr.y + (baseV[1][1]*mFactor[0] + baseV[2][1]*mFactor[1] + baseV[3][1]*mFactor[2] + baseV[4][1]*mFactor[3]);
500
                buffer[offset+2] = (next.z-curr.z)*time + curr.z + (baseV[1][2]*mFactor[0] + baseV[2][2]*mFactor[1] + baseV[3][2]*mFactor[2] + baseV[4][2]*mFactor[3]);
501
                buffer[offset+3] = (next.w-curr.w)*time + curr.w + (baseV[1][3]*mFactor[0] + baseV[2][3]*mFactor[1] + baseV[3][3]*mFactor[2] + baseV[4][3]*mFactor[3]);
502
                buffer[offset+4] = (next.v-curr.v)*time + curr.v + (baseV[1][4]*mFactor[0] + baseV[2][4]*mFactor[1] + baseV[3][4]*mFactor[2] + baseV[4][4]*mFactor[3]);
503
                }
504
              else
505
                {
506
                buffer[offset  ] = (next.x-curr.x)*time + curr.x;
507
                buffer[offset+1] = (next.y-curr.y)*time + curr.y;
508
                buffer[offset+2] = (next.z-curr.z)*time + curr.z;
509
                buffer[offset+3] = (next.w-curr.w)*time + curr.w;
510
                buffer[offset+4] = (next.v-curr.v)*time + curr.v;
511
                }
512
                
513
              break;
514
      default:computeSegmentAndTime(time);
515

    
516
              if( mTmpVec>=0 && mTmpVec<numPoints )
517
                {
518
                if( cacheDirty ) recomputeCache();  // recompute cache if we have added or remove vectors since last computation
519
                else if( mSegment!= mTmpSeg )       // ...or if we have just passed a vector and the vector we are currently flying to has changed
520
                  {
521
                  int vecNext = getNext(mTmpVec,time);
522
                  next = vv.elementAt(vecNext);
523
                  tmpCache2 = vc.elementAt(vecNext);
524

    
525
                  if( tmpCache2.cached[0]!=next.x || tmpCache2.cached[1]!=next.y || tmpCache2.cached[2]!=next.z || tmpCache2.cached[3]!=next.w || tmpCache2.cached[4]!=next.v ) recomputeCache();
526
                  }
527

    
528
                if( mSegment!= mTmpSeg && vn!=null ) vn.elementAt(mTmpVec).computeNoise();
529

    
530
                mSegment = mTmpSeg;
531
                time = mTmpTime-mTmpVec;
532
                tmpCache1 = vc.elementAt(mTmpVec);
533
                if( mSpeedMode==SPEED_MODE_SEGMENT_CONSTANT ) time = smoothSpeed(time, tmpCache1);
534

    
535
                if( vn!=null )
536
                  {
537
                  time = noise(time,mTmpVec);
538
              
539
                  computeOrthonormalBaseMore(time, tmpCache1);
540

    
541
                  buffer[offset  ]= ((tmpCache1.a[0]*time+ tmpCache1.b[0])*time+ tmpCache1.c[0])*time+ tmpCache1.d[0] + (baseV[1][0]*mFactor[0] + baseV[2][0]*mFactor[1] + baseV[3][0]*mFactor[2] + baseV[4][0]*mFactor[3]);
542
                  buffer[offset+1]= ((tmpCache1.a[1]*time+ tmpCache1.b[1])*time+ tmpCache1.c[1])*time+ tmpCache1.d[1] + (baseV[1][1]*mFactor[0] + baseV[2][1]*mFactor[1] + baseV[3][1]*mFactor[2] + baseV[4][1]*mFactor[3]);
543
                  buffer[offset+2]= ((tmpCache1.a[2]*time+ tmpCache1.b[2])*time+ tmpCache1.c[2])*time+ tmpCache1.d[2] + (baseV[1][2]*mFactor[0] + baseV[2][2]*mFactor[1] + baseV[3][2]*mFactor[2] + baseV[4][2]*mFactor[3]);
544
                  buffer[offset+3]= ((tmpCache1.a[3]*time+ tmpCache1.b[3])*time+ tmpCache1.c[3])*time+ tmpCache1.d[3] + (baseV[1][3]*mFactor[0] + baseV[2][3]*mFactor[1] + baseV[3][3]*mFactor[2] + baseV[4][3]*mFactor[3]);
545
                  buffer[offset+4]= ((tmpCache1.a[4]*time+ tmpCache1.b[4])*time+ tmpCache1.c[4])*time+ tmpCache1.d[4] + (baseV[1][4]*mFactor[0] + baseV[2][4]*mFactor[1] + baseV[3][4]*mFactor[2] + baseV[4][4]*mFactor[3]);
546
                  }
547
                else
548
                  {
549
                  buffer[offset  ]= ((tmpCache1.a[0]*time+ tmpCache1.b[0])*time+ tmpCache1.c[0])*time+ tmpCache1.d[0];
550
                  buffer[offset+1]= ((tmpCache1.a[1]*time+ tmpCache1.b[1])*time+ tmpCache1.c[1])*time+ tmpCache1.d[1];
551
                  buffer[offset+2]= ((tmpCache1.a[2]*time+ tmpCache1.b[2])*time+ tmpCache1.c[2])*time+ tmpCache1.d[2];
552
                  buffer[offset+3]= ((tmpCache1.a[3]*time+ tmpCache1.b[3])*time+ tmpCache1.c[3])*time+ tmpCache1.d[3];
553
                  buffer[offset+4]= ((tmpCache1.a[4]*time+ tmpCache1.b[4])*time+ tmpCache1.c[4])*time+ tmpCache1.d[4];
554
                  }
555
 
556
                break;
557
                }
558
      }
559
    }  
560

    
561
  }
562
///////////////////////////////////////////////////////////////////////////////////////////////////
563
//
(11-11/18)