FreeWRL/FreeX3D  3.0.0
Component_Followers.c
1 /*
2 
3 
4 X3D Followers Component
5 
6 */
7 
8 
9 /****************************************************************************
10  This file is part of the FreeWRL/FreeX3D Distribution.
11 
12  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13 
14  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15  it under the terms of the GNU Lesser Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  GNU General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26 ****************************************************************************/
27 
28 #include <config.h>
29 #include <system.h>
30 #include <display.h>
31 #include <internal.h>
32 #include <iglobal.h>
33 #include <libFreeWRL.h>
34 
35 #include "../vrml_parser/Structs.h"
36 #include "../vrml_parser/CRoutes.h"
37 #include "../main/headers.h"
38 
39 #include "../world_script/fieldSet.h"
40 #include "../x3d_parser/Bindable.h"
41 #include "Collision.h"
42 #include "quaternion.h"
43 #include "Viewer.h"
44 #include "../opengl/Frustum.h"
45 #include "../opengl/Material.h"
46 #include "../opengl/OpenGL_Utils.h"
47 #include "../input/EAIHelpers.h" /* for newASCIIString() */
48 
49 #include "Polyrep.h"
50 #include "LinearAlgebra.h"
51 //#include "Component_Followers.h"
52 #include "Children.h"
53 
54 
55 typedef struct pComponent_Followers{
56  int something;
58 void *Component_Followers_constructor(){
59  void *v = MALLOCV(sizeof(struct pComponent_Followers));
60  memset(v,0,sizeof(struct pComponent_Followers));
61  return v;
62 }
63 void Component_Followers_init(struct tComponent_Followers *t){
64  //public
65  //private
66  t->prv = Component_Followers_constructor();
67  {
69  p->something = 0;
70  }
71 }
72 void Component_Followers_clear(struct tComponent_Followers *t){
73  //public
74 }
75 
76 
77 
78 //ppComponent_Followers p = (ppComponent_Followers)gglobal()->Component_Followers.prv;
79 
80 void do_ColorChaserTick(void * ptr);
81 void do_ColorDamperTick(void * ptr);
82 void do_CoordinateChaserTick(void * ptr);
83 void do_CoordinateDamperTick(void * ptr);
84 void do_OrientationChaserTick(void * ptr);
85 void do_OrientationDamperTick(void * ptr);
86 void do_PositionChaserTick(void * ptr);
87 void do_ColorDamperTick(void * ptr);
88 void do_PositionChaserTick(void * ptr);
89 void do_PositionDamperTick(void * ptr);
90 void do_PositionChaser2DTick(void * ptr);
91 void do_PositionDamper2DTick(void * ptr);
92 void do_ScalarChaserTick(void * ptr);
93 void do_ScalarDamperTick(void * ptr);
94 void do_TexCoordChaser2DTick(void * ptr);
95 void do_TexCoordDamper2DTick(void * ptr);
96 
97 
98 
99 /*
100  adapted from
101  http://www.web3d.org/x3d/content/examples/Basic/Followers/index.html
102 */
103 
104 
105 //for now we'll put the private variables static,
106 // but they would go into a _private struct field in the node
107 static int Buffer_length = 10;
108 //static int cNumSupports = 10;
109 //static int bInitialized = 0;
110 //static double BufferEndTime = 0.0;
111 //static double cStepTime = 0.0;
112 //static struct SFVec3f previousValue = { 0.0f, 0.0f, 0.0f};
113 //static struct SFVec3f destination = {0.0f,0.0f,0.0f};
114 //static struct SFVec3f Buffer[10];
115 
116 /*
117 //in theory you could have something like this,
118 // and some generalized functions that delegate to some
119 // function pointers or switch_case on type of element.
120 //global constants
121  static int Buffer_length = 10;
122  static int cNumSupports = 10;
123 
124 //common, can initialize to common
125 typedef struct chaser_struct {
126  int bInitialized;
127  double BufferEndTime;
128  double cStepTime;
129  //offsetofs
130  void *value_changed;
131  void *isActive;
132  void *set_destination;
133  void *set_value;
134  //privates
135  void *previousValue;
136  void *destination;
137  void *Buffer;
138 }chaser_struct;
139 typedef struct chaser_data {
140 struct SFVec3f previousValue;
141 struct SFVec3f destination;
142 struct SFVec3f Buffer[10];
143 }chaser_data;
144 
145 There are a number of ways to abstract types for generic algorithms in C
146 a. ## macroization - used frequently in freewrl, however MF and SF still need different treatement
147  can go SFa = SFb, but MFa = MFb won't deep copy the p*
148  similar to templates in C++, generates separate code for each type during compilation
149 b. low-level functions like ADD have a switch-case on fieldtype (need to pass in field type)
150 c. function pointers that know the type, to abstract handling of an opaque type
151 I'll try a combination here, as an experiment.
152 A. keeping a certain order to the fields:
153 - non-field-type-specific fields come first -int, bool, time- then can use a generic node->fieldname
154 - value_changed the first field-type-specific field so offsetof(,value_changed) is the same for all chasers (and dampers)
155 B. using c. above, generic functions for handling opaque types, with functions knowing the type
156 
157 */
158 
159 //goal: prepare the absolute addresses of field-type-specific fields
160 // for chaser and damper to generisize algos without using ## macros and offsetof
161 // which compiles to more code
162 // the following _ptrs structs would be populated in do_ on initialization
163 // for each node instance (since absolute pointers vary with instance)
164 typedef struct chaser_ptrs {
165  //public
166  void *value_changed;
167  void *initialDestination;
168  void *initialValue;
169  void *set_destination;
170  void *set_value;
171  //private
172  void *_buffer;
173  void *_previousValue;
174  void *_destination;
175 }chaser_ptrs;
176 typedef struct damper_ptrs {
177  //public
178  void *value_changed;
179  void *initialDestination;
180  void *initialValue;
181  void *set_destination;
182  void *set_value;
183  //private
184  void *_values;
185  void *_input;
186 } damper_ptrs;
187 
188 //goal: abstract a few numerical field types without using ## macroization
189 //- including SF and MF in same interface, so algos can be generic
190 // this should be static for a fieldtype
191 #define VOIDFN (void(*))
192 #define FLOATFN (float (*)(void *))
193 #define INTFN (int (*) (void *, void *))
194 #define VOIDPTR (void *)
195 typedef struct ftype {
196  int type;
197  void* (*copy)(void *T,void *A);
198  void* (*add)(void *T,void* A,void* B);
199  void* (*dif)(void *T,void* A,void* B);
200  void* (*scale)(void *T,void* A,float S);
201  void* (*lerp)(void *T,void *A, void *B, float alpha);
202  float (*dist)(void* A);
203  int (*same)(void* A,void* B);
204  int (*approx)(void* A,void* B);
205  void* (*arr)(void* A,int i); //for sf = array[i]
206  //void (*mfi)(void* A,int i); //for sf = mf.p[i]
207  void **tmp;
208  //lerp vs slerp for orientationChaser?
209 }ftype;
210 
211 //example for float, but I need SFVec3f versions for position
212 float *arr3f(float *A, int i){
213  //memcpy(T,&A[3*i],3*sizeof(float));
214  return &A[3*i];
215 }
216 float *veclerp3f(float *T, float *A, float *B, float alpha){
217  int i;
218  for(i=0;i<3;i++){
219  T[i] = (1.0f - alpha)*A[i] + alpha*B[i];
220  }
221  return T;
222 }
223 float tmp3f1[6][3];
224 void *tmp3f [] = {&tmp3f[0],&tmp3f[1],&tmp3f[2],&tmp3f[3],&tmp3f[4],&tmp3f[5]};
225 
226 
227 ftype ftype_vec3f = {
228  -1, //not a real type, just for warm-up
229  VOIDFN veccopy3f,
230  VOIDFN vecadd3f,
231  VOIDFN vecdif3f,
232  VOIDFN vecscale3f,
233  VOIDFN veclerp3f,
234  FLOATFN veclength3f,
235  INTFN vecsame3f,
236  INTFN vecsame3f,
237  VOIDFN arr3f,
238  VOIDPTR tmp3f,
239 };
240 
241 struct SFVec3f *sfvec3f_copy(struct SFVec3f* T, struct SFVec3f *A){
242  veccopy3f(T->c,A->c);
243  return T;
244 }
245 struct SFVec3f *sfvec3f_add(struct SFVec3f* T, struct SFVec3f *A, struct SFVec3f *B){
246  vecadd3f(T->c,A->c,B->c);
247  return T;
248 }
249 struct SFVec3f *sfvec3f_dif(struct SFVec3f* T, struct SFVec3f *A, struct SFVec3f *B){
250  vecdif3f(T->c,A->c,B->c);
251  return T;
252 }
253 struct SFVec3f *sfvec3f_scale(struct SFVec3f* T, struct SFVec3f *A, float S){
254  vecscale3f(T->c,A->c,S);
255  return T;
256 }
257 struct SFVec3f *sfvec3f_lerp(struct SFVec3f* T, struct SFVec3f *A, struct SFVec3f *B, float S){
258  veclerp3f(T->c,A->c,B->c,S);
259  return T;
260 }
261 float sfvec3f_dist(struct SFVec3f* A){
262  return veclength3f(A->c);
263 }
264 int sfvec3f_same(struct SFVec3f *A, struct SFVec3f *B){
265  return vecsame3f(A->c,B->c);
266 }
267 struct SFVec3f *sfvec3f_arr(struct SFVec3f *A, int i){
268  return &A[i];
269 }
270 struct SFVec3f sfvec3f_tmps[6];
271 void *sfvec3f_tmp [] = {&sfvec3f_tmps[0],&sfvec3f_tmps[1],&sfvec3f_tmps[2],&sfvec3f_tmps[3],&sfvec3f_tmps[4],&sfvec3f_tmps[5]};
272 ftype ftype_sfvec3f = {
273  FIELDTYPE_SFVec3f,
274  VOIDFN sfvec3f_copy,
275  VOIDFN sfvec3f_add,
276  VOIDFN sfvec3f_dif,
277  VOIDFN sfvec3f_scale,
278  VOIDFN sfvec3f_lerp,
279  FLOATFN sfvec3f_dist,
280  INTFN sfvec3f_same,
281  INTFN sfvec3f_same,
282  VOIDFN sfvec3f_arr,
283  VOIDPTR sfvec3f_tmp,
284 };
285 #define NEWWAY 1
286 #ifdef NEWWAY
287 void chaser_init(struct X3D_PositionChaser *node)
288 {
289  int C;
290  chaser_ptrs *p = node->_p;
291  ftype *t = node->_t;
292 
293  //struct SFVec3f *buffer = (struct SFVec3f*)node->_buffer;
294  //node->_destination = node->initialDestination;
295  t->copy(p->_destination,p->initialDestination);
296  //buffer[0]= node->initialDestination; //initial_destination;
297  t->copy(t->arr(p->_buffer,0),p->initialDestination);
298  for(C= 1; C<Buffer_length; C++ )
299  //buffer[C]= node->initialValue; //initial_value;
300  t->copy(t->arr(p->_buffer,C),p->initialValue);
301  // node->_previousvalue= node->initialValue; //initial_value;
302  t->copy(p->_previousValue,p->initialValue);
303  node->_steptime= node->duration / (double) Buffer_length; //cNumSupports;
304 }
305 double chaser_UpdateBuffer(struct X3D_PositionChaser *node, double Now)
306 {
307  int C;
308  double Frac;
309  //struct SFVec3f *buffer = (struct SFVec3f*)node->_buffer;
310  chaser_ptrs *p = node->_p;
311  ftype *t = node->_t;
312 
313  Frac = (Now - node->_bufferendtime) / node->_steptime;
314  // is normally < 1. When it has grown to be larger than 1, we have to shift the array because the step response
315  // of the oldest entry has already reached its destination, and it's time for a newer entry.
316  // has already reached it
317  // In the case of a very low frame rate, or a very short cStepTime we may need to shift by more than one entry.
318 
319  if(Frac >= 1.0)
320  {
321  int NumToShift= (int)floor(Frac);
322  Frac-= (double) NumToShift;
323  if(NumToShift < Buffer_length)
324  { // normal case.
325 
326  //node->_previousvalue= buffer[Buffer_length - NumToShift];
327  t->copy(p->_previousValue,t->arr(p->_buffer,Buffer_length - NumToShift));
328  for( C= Buffer_length - 1; C>=NumToShift; C-- )
329  //buffer[C]= buffer[C - NumToShift];
330  t->copy(t->arr(p->_buffer,C),t->arr(p->_buffer,C - NumToShift));
331  for( C= 0; C<NumToShift; C++ )
332  {
333  // Hmm, we have a destination value, but don't know how it has
334  // reached the current state.
335  // Therefore we do a linear interpolation from the latest value in the buffer to destination.
336  //float tmp1[3],tmp2[3];
337  float Alpha= (float)C / (float)NumToShift;
338  // might need to chain functions like this backward:
339  // float *vecadd3f(float *c, float *a, float *b)
340  // and feed it temps in the *c variable
341  // and in the last step use Buffer[] as *c
342  t->lerp(t->arr(p->_buffer,C),p->_destination,t->arr(p->_buffer,NumToShift),Alpha);
343  // vecadd3f(buffer[C].c,vecscale3f(tmp1,buffer[NumToShift].c,Alpha),vecscale3f(tmp2,node->_destination.c,1.0f - Alpha));
344  //}
345  }
346  }else
347  {
348  // degenerated case:
349  //
350  // We have a _VERY_ low frame rate...
351  // we can only guess how we should fill the array.
352  // Maybe we could write part of a linear interpolation
353  // from Buffer[0] to destination, that goes from BufferEndTime to Now
354  // (possibly only the end of the interpolation is to be written),
355  // but if we rech here we are in a very degenerate case...
356  // Thus we just write destination to the buffer.
357  //node->_previousvalue= NumToShift == Buffer_length? buffer[0] : node->_destination;
358  if(NumToShift == Buffer_length)
359  t->copy(p->_previousValue,t->arr(p->_buffer,0));
360  else
361  t->copy(p->_previousValue,p->_destination);
362  for( C= 0; C<Buffer_length; C++ )
363  //buffer[C]= node->_destination;
364  t->copy(t->arr(p->_buffer,C),p->_destination);
365  }
366  node->_bufferendtime+= NumToShift * node->_steptime;
367  }
368  return Frac;
369 }
370 //when a route toNode.toField is PositionChaser.set_destination
371 //we need to call this function (somehow) much like a script?
372 //
373 void chaser_set_destination(struct X3D_PositionChaser *node, double Now)
374 {
375  chaser_ptrs *p = node->_p;
376  ftype *t = node->_t;
377 
378  // node->_destination= Dest;
379  t->copy(p->_destination,p->set_destination);
380  // Somehow we assign to Buffer[-1] and wait untill this gets shifted into the real buffer.
381  // Would we assign to Buffer[0] instead, we'd have no delay, but this would create a jump in the
382  // output because Buffer[0] is associated with a value in the past.
383  chaser_UpdateBuffer(node, Now);
384 }
385 // This function defines the shape of how the output responds to the input.
386 // It must accept values for T in the range 0 <= T <= 1.
387 // In order to create a smooth animation, it should return 0 for T == 0,
388 // 1 for T == 1 and be sufficient smooth in the range 0 <= T <= 1.
389 
390 // It should be optimized for speed, in order for high performance. It's
391 // executed Buffer.length + 1 times each simulation tick.
392 
393 double chaser_StepResponseCore(double T)
394 {
395  return .5 - .5 * cos(T * PI);
396 }
397 double chaser_StepResponse(struct X3D_PositionChaser *node, double t)
398 {
399  if(t < 0.0)
400  return 0.0;
401  if(t > node->duration)
402  return 1.0;
403  // When optimizing for speed, the above two if(.) cases can be omitted,
404  // as this funciton will not be called for values outside of 0..duration.
405  return chaser_StepResponseCore(t / node->duration);
406 }
407 
408 void chaser_tick(struct X3D_PositionChaser *node, double Now)
409 {
410  int C;
411  double Frac, Alpha;
412  //struct SFVec3f Output;
413  //struct SFVec3f DeltaIn;
414  //struct SFVec3f DeltaOut;
415  void *Output, *DeltaIn, *DeltaOut;
416  // OLDCODE UNUSED struct SFVec3f *buffer = (struct SFVec3f*)node->_buffer;
417  chaser_ptrs *p = node->_p;
418  ftype *t = node->_t;
419 
420  Output = t->tmp[3];
421  DeltaIn = t->tmp[4];
422  DeltaOut = t->tmp[5];
423 
424 
425  //chaser_CheckInit(node);
426  if(!node->_bufferendtime)
427  {
428  node->_bufferendtime= Now; // first event we received, so we are in the initialization phase.
429  //node->value_changed= node->initialValue; //initial_value;
430  t->copy(p->value_changed,p->initialValue);
431  return;
432  }
433  Frac= chaser_UpdateBuffer(node, Now);
434  // Frac is a value in 0 <= Frac < 1.
435 
436  // Now we can calculate the output.
437  // This means we calculate the delta between each entry in Buffer and its previous
438  // entries, calculate the step response of each such step and add it to form the output.
439 
440  // The oldest vaule Buffer[Buffer.length - 1] needs some extra thought, because it has
441  // no previous value. More exactly, we haven't stored a previous value anymore.
442  // However, the step response of that missing previous value has already reached its
443  // destination, so we can - would we have that previous value - use this as a start point
444  // for adding the step responses.
445  // Actually UpdateBuffer(.) maintains this value in
446 
447  if(t->type == FIELDTYPE_SFRotation){
448  //SFRotation - I think I have the SFRotation working below in the regular section
449  // - but to prove with type abstractions you can still do special cases, here's the more
450  // explicitly SFRotation version adapted from prototype example code in javascript
451  //var Output= previousValue;
452  t->copy(Output,p->_previousValue);
453 
454  //var DeltaIn= previousValue.inverse().multiply(Buffer[Buffer.length - 1]);
455  t->dif(DeltaIn,t->arr(p->_buffer,Buffer_length -1),p->_previousValue);
456  Alpha = chaser_StepResponse(node,((double)(Buffer_length - 1) + Frac) * node->_steptime);
457  //Output= Output.slerp(Output.multiply(DeltaIn), StepResponse((Buffer.length - 1 + Frac) * cStepTime));
458  t->lerp(Output,Output,t->add(t->tmp[0],Output,DeltaIn),(float)Alpha);
459  for(C= Buffer_length - 2; C>=0; C-- )
460  {
461  // var DeltaIn= Buffer[C + 1].inverse().multiply(Buffer[C]);
462  t->dif(DeltaIn,t->arr(p->_buffer,C),t->arr(p->_buffer,C+1));
463 
464  Alpha = chaser_StepResponse(node,((double)C + Frac) * node->_steptime);
465  // Output= Output.slerp(Output.multiply(DeltaIn), StepResponse((C + Frac) * cStepTime));
466  t->lerp(Output,Output,t->add(t->tmp[0],Output,DeltaIn),(float)Alpha);
467  }
468 
469  }else{
470  //everything else
471  //Output= node->_previousvalue;
472  t->copy(Output,p->_previousValue);
473  //DeltaIn= Buffer[Buffer_length - 1].subtract(previousValue);
474  //vecdif3f(DeltaIn.c,buffer[Buffer_length - 1].c,node->_previousvalue.c);
475  t->dif(DeltaIn,t->arr(p->_buffer,Buffer_length -1),p->_previousValue);
476 
477  Alpha = chaser_StepResponse(node,((double)(Buffer_length - 1) + Frac) * node->_steptime);
478 
479  //DeltaOut= DeltaIn.multiply(StepResponse((Buffer_length - 1 + Frac) * cStepTime));
480  //vecscale3f(DeltaOut.c,DeltaIn.c,(float)chaser_StepResponse(node,((double)Buffer_length - 1.0 + Frac) * node->_steptime));
481  t->scale(DeltaOut,DeltaIn,(float)Alpha);
482 
483  //Output= Output.add(DeltaOut);
484  //vecadd3f(Output.c,Output.c,DeltaOut.c);
485  t->add(Output,Output,DeltaOut);
486 
487  for(C= Buffer_length - 2; C>=0; C-- )
488  {
489  //DeltaIn= Buffer[C].subtract(Buffer[C + 1]);
490  //vecdif3f(DeltaIn.c,buffer[C].c,buffer[C+1].c);
491  t->dif(DeltaIn,t->arr(p->_buffer,C),t->arr(p->_buffer,C+1));
492 
493  Alpha = chaser_StepResponse(node,((double)C + Frac) * node->_steptime);
494 
495  //DeltaOut= DeltaIn.multiply(StepResponse((C + Frac) * cStepTime));
496  //vecscale3f(DeltaOut.c,DeltaIn.c,(float)chaser_StepResponse(node,((double)C + Frac) * node->_steptime));
497  t->scale(DeltaOut,DeltaIn,(float)Alpha);
498  //Output= Output.add(DeltaOut);
499  //vecadd3f(Output.c,Output.c,DeltaOut.c);
500  t->add(Output,Output,DeltaOut);
501  }
502  }
503  //if(!vecsame3f(Output.c,node->value_changed.c)){
504  if(!t->same(Output,p->value_changed)){
505  t->copy(p->value_changed,Output);
506  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, value_changed));
507  }
508 }
509 void chaser_set_value(struct X3D_PositionChaser *node)
510 {
511  chaser_ptrs *p = node->_p;
512  ftype *t = node->_t;
513 
514  //node->value_changed= opos;
515  t->copy(p->value_changed,p->set_value);
516  //node->initialValue = opos;
517  t->copy(p->initialValue,p->set_value);
518  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, value_changed));
519  node->isActive = TRUE;
520  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
521 }
522 
523 
524 void do_PositionChaserTick(void * ptr){
525  double Now;
526  struct X3D_PositionChaser *_node = (struct X3D_PositionChaser *)ptr;
527  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr;
528  if(!node) return;
529  if(!_node->_buffer){
530  chaser_ptrs *p = MALLOCN(node,sizeof(chaser_ptrs));
531  _node->_buffer = REALLOCN(node,_node->_buffer,Buffer_length * sizeof(struct SFVec3f));
532  node->_t = &ftype_sfvec3f;
533  node->_p = p;
534  p->initialDestination = &_node->initialDestination;
535  p->initialValue = &_node->initialValue;
536  p->set_destination = &_node->set_destination;
537  p->set_value = &_node->set_value;
538  p->value_changed = &_node->value_changed;
539  p->_buffer = _node->_buffer;
540  p->_destination = &_node->_destination;
541  p->_previousValue = &_node->_previousvalue;
542  chaser_init(node);
543  }
544  Now = TickTime();
545  if(NODE_NEEDS_COMPILING){
546  chaser_ptrs *p = node->_p;
547  ftype *t = node->_t;
548 
549  node->isActive = TRUE;
550  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
551  //Q how to tell which set_ was set: set_destination or set_value?
552  //if(!vecsame3f(node->set_destination.c,node->_destination.c))
553  if(!t->same(p->set_destination,p->_destination))
554  chaser_set_destination(node, Now);
555  //else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
556  else if(!t->same(p->set_value,p->initialValue))
557  chaser_set_value(node);
558  MARK_NODE_COMPILED
559  }
560  if(node->isActive)
561  chaser_tick(node,Now);
562 }
563 
564 /*
565  //positiondamper
566 
567 */
568 //static int bInitializedD = FALSE;
569 //static double lastTick = 0.0;
570 //static int bNeedToTakeFirstInput = TRUE;
571 //static struct SFVec3f value5 = {0.0f,0.0f,0.0f};
572 //static struct SFVec3f value4 = {0.0f,0.0f,0.0f};
573 //static struct SFVec3f value3 = {0.0f,0.0f,0.0f};
574 //static struct SFVec3f value2 = {0.0f,0.0f,0.0f};
575 //static struct SFVec3f value1 = {0.0f,0.0f,0.0f};
576 //static struct SFVec3f input = {0.0f,0.0f,0.0f};
577 //
578 
579 
580 void damper_set_value(struct X3D_PositionDamper *node, void *opos);
581 void damper_Init(struct X3D_PositionDamper *node)
582 {
583  damper_ptrs *p = node->_p;
584  // OLDCODE UNUSED ftype *t = node->_t;
585 
586  node->_takefirstinput = TRUE;
587  //damper_set_value(node,node->initialValue);
588  damper_set_value(node,p->initialValue);
589  node->isActive = TRUE;
590  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
591 }
592 
593 float damper_GetDist(struct X3D_PositionDamper *node)
594 {
595  float dist;
596  damper_ptrs *p = node->_p;
597  ftype *t = node->_t;
598 
599  //struct SFVec3f *values = (struct SFVec3f *)node->_values;
600 
601  //double dist= value1.subtract(node->initialDestination).length();
602  //dist = veclength3f(vecdif3f(tmp,values[0].c,node->_input.c));
603  dist = t->dist(t->dif(t->tmp[0],t->arr(p->_values,0),p->_input));
604  if(node->order > 1)
605  {
606  //double dist2= value2.subtract(value1).length();
607  //float dist2 = veclength3f(vecdif3f(tmp,values[1].c,values[0].c));
608  float dist2 = t->dist(t->dif(t->tmp[0],t->arr(p->_values,1),t->arr(p->_values,0)));
609  if( dist2 > dist) dist= dist2;
610  }
611  if(node->order > 2)
612  {
613  //double dist3= value3.subtract(value2).length();
614  //float dist3 = veclength3f(vecdif3f(tmp,values[2].c,values[1].c));
615  float dist3 = t->dist(t->dif(t->tmp[0],t->arr(p->_values,2),t->arr(p->_values,1)));
616  if( dist3 > dist) dist= dist3;
617  }
618  if(node->order > 3)
619  {
620  //double dist4= value4.subtract(value3).length();
621  //float dist4 = veclength3f(vecdif3f(tmp,values[3].c,values[2].c));
622  float dist4 = t->dist(t->dif(t->tmp[0],t->arr(p->_values,3),t->arr(p->_values,2)));
623  if( dist4 > dist) dist= dist4;
624  }
625  if(node->order > 4)
626  {
627  //double dist5= value5.subtract(value4).length();
628  //float dist5 = veclength3f(vecdif3f(tmp,values[4].c, values[3].c));
629  float dist5 = t->dist(t->dif(t->tmp[0],t->arr(p->_values,4),t->arr(p->_values,3)));
630  if( dist5 > dist) dist= dist5;
631  }
632  return dist;
633 }
634 void damper_set_value(struct X3D_PositionDamper *node, void *opos)
635 {
636  int i;
637  damper_ptrs *p = node->_p;
638  ftype *t = node->_t;
639 
640  //struct SFVec3f *values = (struct SFVec3f *)node->_values;
641  node->_takefirstinput = FALSE;
642  //values[0]= values[1]= values[2]= values[3]= values[4]= opos;
643  for(i=0;i<5;i++)
644  t->copy(t->arr(p->_values,i),opos);
645  //node->value_changed= opos;
646  t->copy(p->value_changed, opos);
647  //node->initialValue = opos;
648  t->copy(p->initialValue,opos);
649  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, value_changed));
650  node->isActive = TRUE;
651  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
652 }
653 
654 void damper_set_destination(struct X3D_PositionDamper *node, void *ipos)
655 {
656  damper_ptrs *p = node->_p;
657  ftype *t = node->_t;
658 
659  if(node->_takefirstinput)
660  {
661  node->_takefirstinput = FALSE;
662  damper_set_value(node,ipos);
663  }
664  //if(!vecsame3f(ipos.c,node->_input.c))
665  if(!t->same(ipos,p->_input))
666  {
667  //node->_input = ipos;
668  t->copy(p->_input,ipos);
669  node->isActive = TRUE;
670  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
671  }
672 }
673 
674 //struct SFVec3f damper_diftimes(struct SFVec3f a, struct SFVec3f b, double alpha){
675 //void* damper_diftimes(struct X3D_PositionDamper *node, void *T, void *A, void *B, double alpha){
676 // struct SFVec3f ret;
677 // float tmp[3], tmp2[3];
678 // damper_ptrs *p = node->_p;
679 // ftype *t = node->_t;
680 //
681 // //input .add(value1.subtract(input ).multiply(alpha))
682 // if(1){
683 // //vecdif3f(tmp,b.c,a.c);
684 // t->dif(t->tmp[0],B,A);
685 // //vecscale3f(tmp2,tmp,(float)alpha);
686 // t->scale(t->tmp[1],t->tmp[0],(float)alpha);
687 // //vecadd3f(ret.c,a.c,tmp2);
688 // t->add(T,A,t->tmp[1]);
689 // }else{
690 // //vecadd3f(ret.c,a.c,vecscale3f(tmp2,vecdif3f(tmp,b.c,a.c),(float)alpha));
691 // t->add(T,A,t->scale(t->tmp[1],t->dif(t->tmp[0],B,A),(float)alpha));
692 // }
693 // return T;
694 //}
695 
696 void tick_damper(struct X3D_PositionDamper *node, double now)
697 {
698  double delta,alpha;
699  float dist;
700  damper_ptrs *p = node->_p;
701  ftype *t = node->_t;
702 
703  //struct SFVec3f *values = (struct SFVec3f *)node->_values;
704 
705  if(!node->_lasttick)
706  {
707  node->_lasttick= now;
708  return;
709  }
710  delta= now - node->_lasttick;
711  node->_lasttick= now;
712  alpha= exp(-delta / node->tau);
713  if(node->_takefirstinput) // then don't do any processing.
714  return;
715 
716  //values[0]= node->order > 0 && node->tau != 0.0
717  // //? input .add(value1.subtract(input ).multiply(alpha))
718  // ? damper_diftimes(node->_input,values[0],alpha)
719  // : node->_input;
720 
721  if(node->order > 0 && node->tau != 0.0)
722  //damper_diftimes(node,t->arr(p->_values,0),p->_input,t->arr(p->_values,0),alpha);
723  t->lerp(t->arr(p->_values,0),p->_input,t->arr(p->_values,0),(float)alpha);
724  else
725  t->copy(t->arr(p->_values,0),p->_input);
726 
727  //values[1]= node->order > 1 && node->tau != 0.0
728  // //? value1.add(value2.subtract(value1).multiply(alpha))
729  // ? damper_diftimes(values[0],values[1],alpha)
730  // : values[0];
731  if(node->order > 1 && node->tau != 0.0)
732  //damper_diftimes(node,t->arr(p->_values,1),t->arr(p->_values,0),t->arr(p->_values,1),alpha);
733  t->lerp(t->arr(p->_values,1),t->arr(p->_values,0),t->arr(p->_values,1),(float)alpha);
734  else
735  t->copy(t->arr(p->_values,1),t->arr(p->_values,0));
736 
737  //values[2]= node->order > 2 && node->tau != 0.0
738  // //? value2.add(value3.subtract(value2).multiply(alpha))
739  // ? damper_diftimes(values[1],values[2],alpha)
740  // : values[1];
741  if(node->order > 2 && node->tau != 0.0)
742  //damper_diftimes(node,t->arr(p->_values,2),t->arr(p->_values,1),t->arr(p->_values,2),alpha);
743  t->lerp(t->arr(p->_values,2),t->arr(p->_values,1),t->arr(p->_values,2),(float)alpha);
744  else
745  t->copy(t->arr(p->_values,2),t->arr(p->_values,1));
746 
747 
748  //values[3]= node->order > 3 && node->tau != 0.0
749  // //? value3.add(value4.subtract(value3).multiply(alpha))
750  // ? damper_diftimes(values[2],values[3],alpha)
751  // : values[2];
752  if(node->order > 3 && node->tau != 0.0)
753  //damper_diftimes(node,t->arr(p->_values,3),t->arr(p->_values,2),t->arr(p->_values,3),alpha);
754  t->lerp(t->arr(p->_values,3),t->arr(p->_values,2),t->arr(p->_values,3),(float)alpha);
755  else
756  t->copy(t->arr(p->_values,3),t->arr(p->_values,2));
757 
758  //values[4]= node->order > 4 && node->tau != 0.0
759  // //? value4.add(value5.subtract(value4).multiply(alpha))
760  // ? damper_diftimes(values[3],values[4],alpha)
761  // : values[3];
762  if(node->order > 4 && node->tau != 0.0)
763  //damper_diftimes(node,t->arr(p->_values,4),t->arr(p->_values,3),t->arr(p->_values,4),alpha);
764  t->lerp(t->arr(p->_values,4),t->arr(p->_values,3),t->arr(p->_values,4),(float)alpha);
765  else
766  t->copy(t->arr(p->_values,4),t->arr(p->_values,3));
767 
768  dist= damper_GetDist(node);
769 
770  if(dist < max(node->tolerance,.001f)) //eps)
771  {
772  int i;
773  //values[0]= values[1]= values[2]= values[3]= values[4]= node->_input;
774  for(i=0;i<5;i++)
775  t->copy(t->arr(p->_values,i),p->_input);
776 
777  //node->value_changed= node->_input;
778  t->copy(p->value_changed,p->_input);
779  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, value_changed));
780  node->isActive = FALSE;
781  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
782  return;
783  }
784  //node->value_changed= values[4];
785  t->copy(p->value_changed,t->arr(p->_values,4));
786  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, value_changed));
787 }
788 void damper_set_tau(struct X3D_PositionDamper *node, double tau){
789  node->_tau = tau;
790  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, tau));
791 }
792 
793 void do_PositionDamperTick(void * ptr){
794  struct X3D_PositionDamper *_node = (struct X3D_PositionDamper *)ptr;
795  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr;
796  if(!node)return;
797  if(!_node->_values){
798  damper_ptrs *p = MALLOCN(node,sizeof(damper_ptrs));
799  node->_t = &ftype_sfvec3f;
800  node->_p = p;
801  _node->_values = REALLOCN(node,_node->_values,5 * sizeof(struct SFVec3f));
802  p->initialDestination = &_node->initialDestination;
803  p->initialValue = &_node->initialValue;
804  p->set_destination = &_node->set_destination;
805  p->set_value = &_node->set_value;
806  p->value_changed = &_node->value_changed;
807  p->_input = &_node->_input;
808  p->_values = _node->_values;
809  //damper_CheckInit(node);
810  damper_Init(node);
811  }
812 
813  if(NODE_NEEDS_COMPILING){
814  //node->isActive = TRUE;
815  damper_ptrs *p = node->_p;
816  ftype *t = node->_t;
817 
818  //if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
819  if(!t->same(p->set_destination,p->_input))
820  //damper_set_destination(node, node->set_destination);
821  damper_set_destination(node, p->set_destination);
822  //set_tau
823  if(node->tau != node->_tau)
824  damper_set_tau(node,node->tau);
825  //set_value
826  //if(!vecsame3f(node->initialValue.c,node->set_value.c))
827  if(!t->same(p->initialValue,p->set_value))
828  //damper_set_value(node,node->set_value);
829  damper_set_value(node,p->set_value);
830  MARK_NODE_COMPILED
831  }
832  if(node->isActive)
833  tick_damper(node,TickTime());
834 }
835 #else //NEWWAY
836 void chaser_init(struct X3D_PositionChaser *node)
837 {
838  int C;
839  struct SFVec3f *buffer = (struct SFVec3f*)node->_buffer;
840  node->_destination = node->initialDestination;
841  buffer[0]= node->initialDestination; //initial_destination;
842  for(C= 1; C<Buffer_length; C++ )
843  buffer[C]= node->initialValue; //initial_value;
844  node->_previousvalue= node->initialValue; //initial_value;
845  node->_steptime= node->duration / (double) Buffer_length; //cNumSupports;
846 }
847 double chaser_UpdateBuffer(struct X3D_PositionChaser *node, double Now)
848 {
849  int C;
850  double Frac;
851  struct SFVec3f *buffer = (struct SFVec3f*)node->_buffer;
852 
853  Frac = (Now - node->_bufferendtime) / node->_steptime;
854  // is normally < 1. When it has grown to be larger than 1, we have to shift the array because the step response
855  // of the oldest entry has already reached its destination, and it's time for a newer entry.
856  // has already reached it
857  // In the case of a very low frame rate, or a very short cStepTime we may need to shift by more than one entry.
858 
859  if(Frac >= 1.0)
860  {
861  int NumToShift= (int)floor(Frac);
862  Frac-= (double) NumToShift;
863  if(NumToShift < Buffer_length)
864  { // normal case.
865 
866  node->_previousvalue= buffer[Buffer_length - NumToShift];
867  for( C= Buffer_length - 1; C>=NumToShift; C-- )
868  buffer[C]= buffer[C - NumToShift];
869  for( C= 0; C<NumToShift; C++ )
870  {
871  // Hmm, we have a destination value, but don't know how it has
872  // reached the current state.
873  // Therefore we do a linear interpolation from the latest value in the buffer to destination.
874  float tmp1[3],tmp2[3];
875  float Alpha= (float)C / (float)NumToShift;
876  // might need to chain functions like this backward:
877  // float *vecadd3f(float *c, float *a, float *b)
878  // and feed it temps in the *c variable
879  // and in the last step use Buffer[] as *c
880  //Buffer[C]= Buffer[NumToShift].multiply(Alpha).add(destination.multiply((1 - Alpha)));
881  //vecadd3f(Buffer[C].c,vecscale3f(Buffer[NumToShift].c,(float)Alpha),vecscale3f(tmp2,destination.c,(1.0f-Alpha));
882  //printf("alf %f ",Alpha);
883  // buff[C] = alpha*buff[NumToShift] + (1-alpha)*destination;
884  if(1){
885  float tmp3[3];
886  vecscale3f(tmp1,buffer[NumToShift].c,Alpha);
887  vecscale3f(tmp2,node->_destination.c,1.0f - Alpha);
888  vecadd3f(tmp3,tmp1,tmp2);
889  veccopy3f(buffer[C].c,tmp3);
890  }else{
891  vecadd3f(buffer[C].c,vecscale3f(tmp1,buffer[NumToShift].c,Alpha),vecscale3f(tmp2,node->_destination.c,1.0f - Alpha));
892  }
893  }
894  }else
895  {
896  // degenerated case:
897  //
898  // We have a _VERY_ low frame rate...
899  // we can only guess how we should fill the array.
900  // Maybe we could write part of a linear interpolation
901  // from Buffer[0] to destination, that goes from BufferEndTime to Now
902  // (possibly only the end of the interpolation is to be written),
903  // but if we rech here we are in a very degenerate case...
904  // Thus we just write destination to the buffer.
905  node->_previousvalue= NumToShift == Buffer_length? buffer[0] : node->_destination;
906 
907  for( C= 0; C<Buffer_length; C++ )
908  buffer[C]= node->_destination;
909  }
910  node->_bufferendtime+= NumToShift * node->_steptime;
911  }
912  return Frac;
913 }
914 //when a route toNode.toField is PositionChaser.set_destination
915 //we need to call this function (somehow) much like a script?
916 //
917 void chaser_set_destination(struct X3D_PositionChaser *node, struct SFVec3f Dest, double Now)
918 {
919  node->_destination= Dest;
920  // Somehow we assign to Buffer[-1] and wait untill this gets shifted into the real buffer.
921  // Would we assign to Buffer[0] instead, we'd have no delay, but this would create a jump in the
922  // output because Buffer[0] is associated with a value in the past.
923  chaser_UpdateBuffer(node, Now);
924 }
925 // This function defines the shape of how the output responds to the input.
926 // It must accept values for T in the range 0 <= T <= 1.
927 // In order to create a smooth animation, it should return 0 for T == 0,
928 // 1 for T == 1 and be sufficient smooth in the range 0 <= T <= 1.
929 
930 // It should be optimized for speed, in order for high performance. It's
931 // executed Buffer.length + 1 times each simulation tick.
932 
933 double chaser_StepResponseCore(double T)
934 {
935  return .5 - .5 * cos(T * PI);
936 }
937 double chaser_StepResponse(struct X3D_PositionChaser *node, double t)
938 {
939  if(t < 0.0)
940  return 0.0;
941  if(t > node->duration)
942  return 1.0;
943  // When optimizing for speed, the above two if(.) cases can be omitted,
944  // as this funciton will not be called for values outside of 0..duration.
945  return chaser_StepResponseCore(t / node->duration);
946 }
947 
948 void chaser_tick(struct X3D_PositionChaser *node, double Now)
949 {
950  int C;
951  double Frac;
952  struct SFVec3f Output;
953  struct SFVec3f DeltaIn;
954  struct SFVec3f DeltaOut;
955  struct SFVec3f *buffer = (struct SFVec3f*)node->_buffer;
956 
957  //chaser_CheckInit(node);
958  if(!node->_bufferendtime)
959  {
960  node->_bufferendtime= Now; // first event we received, so we are in the initialization phase.
961  node->value_changed= node->initialValue; //initial_value;
962  return;
963  }
964  Frac= chaser_UpdateBuffer(node, Now);
965  // Frac is a value in 0 <= Frac < 1.
966 
967  // Now we can calculate the output.
968  // This means we calculate the delta between each entry in Buffer and its previous
969  // entries, calculate the step response of each such step and add it to form the output.
970 
971  // The oldest vaule Buffer[Buffer.length - 1] needs some extra thought, because it has
972  // no previous value. More exactly, we haven't stored a previous value anymore.
973  // However, the step response of that missing previous value has already reached its
974  // destination, so we can - would we have that previous value - use this as a start point
975  // for adding the step responses.
976  // Actually UpdateBuffer(.) maintains this value in
977 
978  Output= node->_previousvalue;
979  //DeltaIn= Buffer[Buffer_length - 1].subtract(previousValue);
980  vecdif3f(DeltaIn.c,buffer[Buffer_length - 1].c,node->_previousvalue.c);
981 
982  //DeltaOut= DeltaIn.multiply(StepResponse((Buffer_length - 1 + Frac) * cStepTime));
983  vecscale3f(DeltaOut.c,DeltaIn.c,(float)chaser_StepResponse(node,((double)Buffer_length - 1.0 + Frac) * node->_steptime));
984  //Output= Output.add(DeltaOut);
985  vecadd3f(Output.c,Output.c,DeltaOut.c);
986  for(C= Buffer_length - 2; C>=0; C-- )
987  {
988  //DeltaIn= Buffer[C].subtract(Buffer[C + 1]);
989  vecdif3f(DeltaIn.c,buffer[C].c,buffer[C+1].c);
990  //DeltaOut= DeltaIn.multiply(StepResponse((C + Frac) * cStepTime));
991  vecscale3f(DeltaOut.c,DeltaIn.c,(float)chaser_StepResponse(node,((double)C + Frac) * node->_steptime));
992  //Output= Output.add(DeltaOut);
993  vecadd3f(Output.c,Output.c,DeltaOut.c);
994  }
995  if(!vecsame3f(Output.c,node->value_changed.c)){
996  node->value_changed= Output;
997  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, value_changed));
998  }
999 }
1000 void chaser_set_value(struct X3D_PositionChaser *node, struct SFVec3f opos)
1001 {
1002  node->value_changed= opos;
1003  node->initialValue = opos;
1004  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, value_changed));
1005  node->isActive = TRUE;
1006  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
1007 }
1008 
1009 
1010 void do_PositionChaserTick(void * ptr){
1011  double Now;
1012  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr;
1013  if(!node) return;
1014  if(!node->_buffer){
1015  node->_buffer = realloc(node->_buffer,Buffer_length * sizeof(struct SFVec3f));
1016  chaser_init(node);
1017  }
1018  Now = TickTime();
1019  if(NODE_NEEDS_COMPILING){
1020  node->isActive = TRUE;
1021  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
1022  //Q how to tell which set_ was set: set_destination or set_value?
1023  if(!vecsame3f(node->set_destination.c,node->_destination.c))
1024  chaser_set_destination(node, node->set_destination,Now);
1025  else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
1026  chaser_set_value(node,node->set_value);
1027  MARK_NODE_COMPILED
1028  }
1029  if(node->isActive)
1030  chaser_tick(node,Now);
1031 }
1032 
1033 /*
1034  //positiondamper
1035 
1036 */
1037 //static int bInitializedD = FALSE;
1038 //static double lastTick = 0.0;
1039 //static int bNeedToTakeFirstInput = TRUE;
1040 //static struct SFVec3f value5 = {0.0f,0.0f,0.0f};
1041 //static struct SFVec3f value4 = {0.0f,0.0f,0.0f};
1042 //static struct SFVec3f value3 = {0.0f,0.0f,0.0f};
1043 //static struct SFVec3f value2 = {0.0f,0.0f,0.0f};
1044 //static struct SFVec3f value1 = {0.0f,0.0f,0.0f};
1045 //static struct SFVec3f input = {0.0f,0.0f,0.0f};
1046 //
1047 
1048 
1049 void damper_set_value(struct X3D_PositionDamper *node, struct SFVec3f opos);
1050 void damper_Init(struct X3D_PositionDamper *node)
1051 {
1052  node->_takefirstinput = TRUE;
1053  damper_set_value(node,node->initialValue);
1054  node->isActive = TRUE;
1055  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
1056 }
1057 
1058 float damper_GetDist(struct X3D_PositionDamper *node)
1059 {
1060  float tmp[3], dist;
1061  struct SFVec3f *values = (struct SFVec3f *)node->_values;
1062 
1063  //double dist= value1.subtract(node->initialDestination).length();
1064  dist = veclength3f(vecdif3f(tmp,values[0].c,node->_input.c));
1065  if(node->order > 1)
1066  {
1067  //double dist2= value2.subtract(value1).length();
1068  float dist2 = veclength3f(vecdif3f(tmp,values[1].c,values[0].c));
1069  if( dist2 > dist) dist= dist2;
1070  }
1071  if(node->order > 2)
1072  {
1073  //double dist3= value3.subtract(value2).length();
1074  float dist3 = veclength3f(vecdif3f(tmp,values[2].c,values[1].c));
1075  if( dist3 > dist) dist= dist3;
1076  }
1077  if(node->order > 3)
1078  {
1079  //double dist4= value4.subtract(value3).length();
1080  float dist4 = veclength3f(vecdif3f(tmp,values[3].c,values[2].c));
1081  if( dist4 > dist) dist= dist4;
1082  }
1083  if(node->order > 4)
1084  {
1085  //double dist5= value5.subtract(value4).length();
1086  float dist5 = veclength3f(vecdif3f(tmp,values[4].c, values[3].c));
1087  if( dist5 > dist) dist= dist5;
1088  }
1089  return dist;
1090 }
1091 void damper_set_value(struct X3D_PositionDamper *node, struct SFVec3f opos)
1092 {
1093  struct SFVec3f *values = (struct SFVec3f *)node->_values;
1094  node->_takefirstinput = FALSE;
1095  values[0]= values[1]= values[2]= values[3]= values[4]= opos;
1096  node->value_changed= opos;
1097  node->initialValue = opos;
1098  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, value_changed));
1099  node->isActive = TRUE;
1100  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
1101 }
1102 
1103 void damper_set_destination(struct X3D_PositionDamper *node, struct SFVec3f ipos)
1104 {
1105  if(node->_takefirstinput)
1106  {
1107  node->_takefirstinput = FALSE;
1108  damper_set_value(node,ipos);
1109  }
1110  if(!vecsame3f(ipos.c,node->_input.c))
1111  {
1112  node->_input = ipos;
1113  node->isActive = TRUE;
1114  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
1115  }
1116 }
1117 
1118 struct SFVec3f damper_diftimes(struct SFVec3f a, struct SFVec3f b, double alpha){
1119  struct SFVec3f ret;
1120  float tmp[3], tmp2[3];
1121  //input .add(value1.subtract(input ).multiply(alpha))
1122  if(1){
1123  vecdif3f(tmp,b.c,a.c);
1124  vecscale3f(tmp2,tmp,(float)alpha);
1125  vecadd3f(ret.c,a.c,tmp2);
1126  }else{
1127  vecadd3f(ret.c,a.c,vecscale3f(tmp2,vecdif3f(tmp,b.c,a.c),(float)alpha));
1128  }
1129  return ret;
1130 }
1131 
1132 void tick_positiondamper(struct X3D_PositionDamper *node, double now)
1133 {
1134  double delta,alpha;
1135  float dist;
1136  struct SFVec3f *values = (struct SFVec3f *)node->_values;
1137 
1138  if(!node->_lasttick)
1139  {
1140  node->_lasttick= now;
1141  return;
1142  }
1143  delta= now - node->_lasttick;
1144  node->_lasttick= now;
1145  alpha= exp(-delta / node->tau);
1146  if(node->_takefirstinput) // then don't do any processing.
1147  return;
1148 
1149  values[0]= node->order > 0 && node->tau != 0.0
1150  //? input .add(value1.subtract(input ).multiply(alpha))
1151  ? damper_diftimes(node->_input,values[0],alpha)
1152  : node->_input;
1153 
1154  values[1]= node->order > 1 && node->tau != 0.0
1155  //? value1.add(value2.subtract(value1).multiply(alpha))
1156  ? damper_diftimes(values[0],values[1],alpha)
1157  : values[0];
1158 
1159  values[2]= node->order > 2 && node->tau != 0.0
1160  //? value2.add(value3.subtract(value2).multiply(alpha))
1161  ? damper_diftimes(values[1],values[2],alpha)
1162  : values[1];
1163 
1164  values[3]= node->order > 3 && node->tau != 0.0
1165  //? value3.add(value4.subtract(value3).multiply(alpha))
1166  ? damper_diftimes(values[2],values[3],alpha)
1167  : values[2];
1168 
1169  values[4]= node->order > 4 && node->tau != 0.0
1170  //? value4.add(value5.subtract(value4).multiply(alpha))
1171  ? damper_diftimes(values[3],values[4],alpha)
1172  : values[3];
1173 
1174  dist= damper_GetDist(node);
1175 
1176  if(dist < max(node->tolerance,.001f)) //eps)
1177  {
1178  values[0]= values[1]= values[2]= values[3]= values[4]= node->_input;
1179  node->value_changed= node->_input;
1180  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, value_changed));
1181  node->isActive = FALSE;
1182  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, isActive));
1183  return;
1184  }
1185  node->value_changed= values[4];
1186  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, value_changed));
1187 }
1188 void damper_set_tau(struct X3D_PositionDamper *node, double tau){
1189  node->_tau = tau;
1190  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper, tau));
1191 }
1192 void do_PositionDamperTick(void * ptr){
1193  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr;
1194  if(!node)return;
1195  if(!node->_values){
1196  node->_values = realloc(node->_values,5 * sizeof(struct SFVec3f));
1197  //damper_CheckInit(node);
1198  damper_Init(node);
1199  }
1200 
1201  if(NODE_NEEDS_COMPILING){
1202  //node->isActive = TRUE;
1203  if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
1204  damper_set_destination(node, node->set_destination);
1205  //set_tau
1206  if(node->tau != node->_tau)
1207  damper_set_tau(node,node->tau);
1208  //set_value
1209  if(!vecsame3f(node->initialValue.c,node->set_value.c))
1210  damper_set_value(node,node->set_value);
1211  MARK_NODE_COMPILED
1212  }
1213  if(node->isActive)
1214  tick_positiondamper(node,TickTime());
1215 }
1216 #endif //NEWWAY
1217 
1218 
1219 void do_ColorChaserTick_default(void * ptr){
1220  struct X3D_ColorChaser *node = (struct X3D_ColorChaser *)ptr;
1221  if(!node)return;
1222  if(NODE_NEEDS_COMPILING){
1223  //default action copy input to output when not implemented
1224  veccopy3f(node->value_changed.c, node->set_destination.c);
1225  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_ColorChaser, value_changed));
1226  MARK_NODE_COMPILED
1227  }
1228 }
1229 void do_ColorDamperTick_default(void * ptr){
1230  struct X3D_ColorDamper *node = (struct X3D_ColorDamper *)ptr;
1231  if(!node)return;
1232  if(NODE_NEEDS_COMPILING){
1233  //default action copy input to output when not implemented
1234  veccopy3f(node->value_changed.c, node->set_destination.c);
1235  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_ColorDamper, value_changed));
1236  MARK_NODE_COMPILED
1237  }
1238 }
1239 void do_ColorChaserTick(void * ptr){
1240  double Now;
1241  struct X3D_ColorChaser *_node = (struct X3D_ColorChaser *)ptr;
1242  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr; //abstract interface
1243  if(!node) return;
1244  if(!_node->_buffer){
1245  chaser_ptrs *p = MALLOCN(node,sizeof(chaser_ptrs));
1246  _node->_buffer = REALLOCN(node,_node->_buffer,Buffer_length * sizeof(struct SFColor)); //**changes with field type
1247  node->_t = &ftype_sfvec3f; //**changes with field type
1248  node->_p = p;
1249  p->initialDestination = &_node->initialDestination;
1250  p->initialValue = &_node->initialValue;
1251  p->set_destination = &_node->set_destination;
1252  p->set_value = &_node->set_value;
1253  p->value_changed = &_node->value_changed;
1254  p->_buffer = _node->_buffer;
1255  p->_destination = &_node->_destination;
1256  p->_previousValue = &_node->_previousvalue;
1257  chaser_init(node);
1258  }
1259  Now = TickTime();
1260  if(NODE_NEEDS_COMPILING){
1261  chaser_ptrs *p = node->_p;
1262  ftype *t = node->_t;
1263 
1264  node->isActive = TRUE;
1265  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
1266  //Q how to tell which set_ was set: set_destination or set_value?
1267  //if(!vecsame3f(node->set_destination.c,node->_destination.c))
1268  if(!t->same(p->set_destination,p->_destination))
1269  chaser_set_destination(node, Now);
1270  //else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
1271  else if(!t->same(p->set_value,p->initialValue))
1272  chaser_set_value(node);
1273  MARK_NODE_COMPILED
1274  }
1275  if(node->isActive)
1276  chaser_tick(node,Now);
1277 }
1278 
1279 void do_ColorDamperTick(void * ptr){
1280  struct X3D_ColorDamper *_node = (struct X3D_ColorDamper *)ptr;
1281  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr; //abstract type
1282  if(!node)return;
1283  if(!_node->_values){
1284  damper_ptrs *p = MALLOCN(node,sizeof(damper_ptrs));
1285  node->_t = &ftype_sfvec3f; //**changes with field type
1286  node->_p = p;
1287  _node->_values = REALLOCN(node,_node->_values,5 * sizeof(struct SFColor)); //**changes with field type
1288  p->initialDestination = &_node->initialDestination;
1289  p->initialValue = &_node->initialValue;
1290  p->set_destination = &_node->set_destination;
1291  p->set_value = &_node->set_value;
1292  p->value_changed = &_node->value_changed;
1293  p->_input = &_node->_input;
1294  p->_values = _node->_values;
1295  //damper_CheckInit(node);
1296  damper_Init(node);
1297  }
1298 
1299  if(NODE_NEEDS_COMPILING){
1300  //node->isActive = TRUE;
1301  damper_ptrs *p = node->_p;
1302  ftype *t = node->_t;
1303 
1304  //if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
1305  if(!t->same(p->set_destination,p->_input))
1306  //damper_set_destination(node, node->set_destination);
1307  damper_set_destination(node, p->set_destination);
1308  //set_tau
1309  if(node->tau != node->_tau)
1310  damper_set_tau(node,node->tau);
1311  //set_value
1312  //if(!vecsame3f(node->initialValue.c,node->set_value.c))
1313  if(!t->same(p->initialValue,p->set_value))
1314  //damper_set_value(node,node->set_value);
1315  damper_set_value(node,p->set_value);
1316  MARK_NODE_COMPILED
1317  }
1318  if(node->isActive)
1319  tick_damper(node,TickTime());
1320 }
1321 
1322 void do_CoordinateChaserTick_default(void * ptr){
1323  struct X3D_CoordinateChaser *node = (struct X3D_CoordinateChaser *)ptr;
1324  if(!node)return;
1325  if(NODE_NEEDS_COMPILING){
1326  //default action copy input to output when not implemented
1327  int n;
1328  n = node->set_destination.n;
1329  node->value_changed.n = n;
1330  node->value_changed.p = REALLOC(node->value_changed.p,n * sizeof(struct SFVec3f));
1331  memcpy(node->value_changed.p,node->set_destination.p,n*sizeof(struct SFVec3f));
1332  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_CoordinateChaser, value_changed));
1333  MARK_NODE_COMPILED
1334  }
1335 }
1336 void do_CoordinateDamperTick_default(void * ptr){
1337  struct X3D_CoordinateDamper *node = (struct X3D_CoordinateDamper *)ptr;
1338  if(!node)return;
1339  if(NODE_NEEDS_COMPILING){
1340  //default action copy input to output when not implemented
1341  int n;
1342  n = node->set_destination.n;
1343  node->value_changed.n = n;
1344  node->value_changed.p = REALLOC(node->value_changed.p,n * sizeof(struct SFVec3f));
1345  memcpy(node->value_changed.p,node->set_destination.p,n*sizeof(struct SFVec3f));
1346  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_CoordinateDamper, value_changed));
1347  MARK_NODE_COMPILED
1348  }
1349 }
1350 
1351 struct Multi_Vec3f *mfvec3f_copy(struct Multi_Vec3f* T, struct Multi_Vec3f *A){
1352  T->p = REALLOC(T->p,A->n * sizeof(struct SFVec3f));
1353  T->n = A->n;
1354  memcpy(T->p,A->p,A->n * sizeof(struct SFVec3f));
1355  return T;
1356 }
1357 struct Multi_Vec3f *mfvec3f_add(struct Multi_Vec3f* T, struct Multi_Vec3f *A, struct Multi_Vec3f *B){
1358  int i;
1359  T->n = min(A->n,B->n);
1360  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec3f));
1361  for(i=0;i<T->n;i++)
1362  sfvec3f_add(&T->p[i],&A->p[i],&B->p[i]);
1363  return T;
1364 }
1365 struct Multi_Vec3f *mfvec3f_dif(struct Multi_Vec3f* T, struct Multi_Vec3f *A, struct Multi_Vec3f *B){
1366  int i;
1367  T->n = min(A->n,B->n);
1368  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec3f));
1369  for(i=0;i<T->n;i++)
1370  sfvec3f_dif(&T->p[i],&A->p[i],&B->p[i]);
1371  return T;
1372 }
1373 struct Multi_Vec3f *mfvec3f_scale(struct Multi_Vec3f* T, struct Multi_Vec3f *A, float S){
1374  int i;
1375  T->n = A->n;
1376  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec3f));
1377  for(i=0;i<T->n;i++)
1378  sfvec3f_scale(&T->p[i],&A->p[i],S);
1379  return T;
1380 }
1381 struct Multi_Vec3f *mfvec3f_lerp(struct Multi_Vec3f* T, struct Multi_Vec3f *A, struct Multi_Vec3f *B, float alpha){
1382  int i;
1383  T->n = A->n;
1384  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec3f));
1385  for(i=0;i<T->n;i++)
1386  sfvec3f_lerp(&T->p[i],&A->p[i],&B->p[i],alpha);
1387  return T;
1388 }
1389 float mfvec3f_dist(struct Multi_Vec3f* A){
1390  int i;
1391  float dist = 0.0f;
1392  for(i=0;i<A->n;i++)
1393  dist += sfvec3f_dist(&A->p[i]);
1394  return dist;
1395 }
1396 int mfvec3f_same(struct Multi_Vec3f *A, struct Multi_Vec3f *B){
1397  int i, isame;
1398  if(A->n != B->n) return FALSE;
1399  isame = TRUE;
1400  for(i=0;i<A->n;i++)
1401  isame = isame && sfvec3f_same(&A->p[i],&B->p[i]);
1402  return isame;
1403 }
1404 struct Multi_Vec3f *mfvec3f_arr(struct Multi_Vec3f *A, int i){
1405  return &A[i];
1406 }
1407 struct Multi_Vec3f mfvec3f_tmps[6];
1408 void *mfvec3f_tmp [] = {&mfvec3f_tmps[0],&mfvec3f_tmps[1],&mfvec3f_tmps[2],&mfvec3f_tmps[3],&mfvec3f_tmps[4],&mfvec3f_tmps[5]};
1409 ftype ftype_mfvec3f = {
1410  FIELDTYPE_MFVec3f,
1411  VOIDFN mfvec3f_copy,
1412  VOIDFN mfvec3f_add,
1413  VOIDFN mfvec3f_dif,
1414  VOIDFN mfvec3f_scale,
1415  VOIDFN mfvec3f_lerp,
1416  FLOATFN mfvec3f_dist,
1417  INTFN mfvec3f_same,
1418  INTFN mfvec3f_same,
1419  VOIDFN mfvec3f_arr,
1420  VOIDPTR mfvec3f_tmp,
1421 };
1422 
1423 
1424 
1425 
1426 
1427 struct SFRotation *sfrotation_inverse(struct SFRotation* T, struct SFRotation *A){
1428  Quaternion qA,qT;
1429  double x,y,z,a;
1430  memcpy(T->c, A->c, sizeof(struct SFRotation));
1431 
1432  /* convert both rotation to quaternion */
1433  vrmlrot_to_quaternion(&qA, (double) A->c[0],
1434  (double) A->c[1], (double) A->c[2], (double) A->c[3]);
1435 
1436  /* invert it */
1437  quaternion_inverse(&qT,&qA);
1438 
1439  /* and return the resultant, as a vrml rotation */
1440  quaternion_to_vrmlrot(&qT, &x, &y, &z, &a);
1441  /* double to floats, can not use pointers... */
1442  T->c[0] = (float) x;
1443  T->c[1] = (float) y;
1444  T->c[2] = (float) z;
1445  T->c[3] = (float) a;
1446  return T;
1447 }
1448 struct SFRotation *sfrotation_multiply(struct SFRotation* T, struct SFRotation *A, struct SFRotation *B){
1449  Quaternion qA,qB,qT;
1450  double x,y,z,a;
1451 
1452  /* convert both rotation to quaternion */
1453  vrmlrot_to_quaternion(&qA, (double) A->c[0],
1454  (double) A->c[1], (double) A->c[2], (double) A->c[3]);
1455 
1456  vrmlrot_to_quaternion(&qB, (double) B->c[0],
1457  (double) B->c[1], (double) B->c[2], (double) B->c[3]);
1458 
1459  /* multiply them */
1460  quaternion_multiply(&qT,&qA,&qB);
1461 
1462  /* and return the resultant, as a vrml rotation */
1463  quaternion_to_vrmlrot(&qT, &x, &y, &z, &a);
1464  /* double to floats, can not use pointers... */
1465  T->c[0] = (float) x;
1466  T->c[1] = (float) y;
1467  T->c[2] = (float) z;
1468  T->c[3] = (float) a;
1469  return T;
1470 }
1471 
1472 struct SFRotation *sfrotation_copy(struct SFRotation* T, struct SFRotation *A){
1473  memcpy(T->c, A->c, sizeof(struct SFRotation));
1474  return T;
1475 }
1476 struct SFRotation *sfrotation_add(struct SFRotation* T, struct SFRotation *A, struct SFRotation *B){
1477  //rotate a rotation by a dif rotation
1478  sfrotation_multiply(T,A,B);
1479  return T;
1480 }
1481 struct SFRotation *sfrotation_dif(struct SFRotation* T, struct SFRotation *A, struct SFRotation *B){
1482  //find the difference between 2 rotations, return the dif as rotation
1483  //T= inverse(B)*A
1484  Quaternion qA,qB,qBI,qT;
1485  double x,y,z,a;
1486 
1487  /* convert both rotation to quaternion */
1488  vrmlrot_to_quaternion(&qA, (double) A->c[0],
1489  (double) A->c[1], (double) A->c[2], (double) A->c[3]);
1490 
1491  vrmlrot_to_quaternion(&qB, (double) B->c[0],
1492  (double) B->c[1], (double) B->c[2], (double) B->c[3]);
1493 
1494 
1495  quaternion_inverse(&qBI,&qB);
1496  /* multiply them */
1497  quaternion_multiply(&qT,&qBI,&qA);
1498 
1499  /* and return the resultant, as a vrml rotation */
1500  quaternion_to_vrmlrot(&qT, &x, &y, &z, &a);
1501  /* double to floats, can not use pointers... */
1502  T->c[0] = (float) x;
1503  T->c[1] = (float) y;
1504  T->c[2] = (float) z;
1505  T->c[3] = (float) a;
1506  return T;
1507 }
1508 struct SFRotation *sfrotation_scale(struct SFRotation* T, struct SFRotation *A, float S){
1509  //vecscale4f(T->c,A->c,S); // doesn't make sense
1510  //I think scale makes sense in linear world when you scale something that starts at the origin
1511  //In the spherical world, 0 would need to be such that if you take a difference rotation
1512  // delta=A-B
1513  // and scale it,
1514  // delta' = delta * scale
1515  //and add it back
1516  //A' = B + delta'
1517  //then A' would be on the same arc as A and B
1518  //to scale that way for an arbitrary scale -like 2.1- with:
1519  //a) quaternions: q^2.1 where ^ means power of:
1520  // do integer multiples then slerp: q2 = q*q; q3=q*q2; q21 = q2.slerp(q3,.1);
1521  //b) axis angle: sfrotation.angle *= 2.1;
1522  sfrotation_copy(T,A);
1523  T->c[3] *= S; //angle *= S;
1524  return T;
1525 }
1526 struct SFRotation *sfrotation_slerp(struct SFRotation* T, struct SFRotation *A, struct SFRotation *B, float alpha){
1527  if (APPROX(alpha, 0.0f)) {
1528  memcpy(T->c,A->c,4*sizeof(float));
1529  } else if (APPROX(alpha, 1.0f)) {
1530  memcpy(T->c,B->c,4*sizeof(float));
1531  } else {
1532  Quaternion quatA, quatB, quatT;
1533  double x,y,z,a;
1534  vrmlrot_to_quaternion(&quatA,
1535  A->c[0],
1536  A->c[1],
1537  A->c[2],
1538  A->c[3]);
1539 
1540  vrmlrot_to_quaternion(&quatB,
1541  B->c[0],
1542  B->c[1],
1543  B->c[2],
1544  B->c[3]);
1545 
1546  quaternion_slerp(&quatT, &quatA, &quatB, (double)alpha);
1547  quaternion_to_vrmlrot(&quatT,&x,&y,&z,&a);
1548  /* double to floats, can not use pointers... */
1549  T->c[0] = (float) x;
1550  T->c[1] = (float) y;
1551  T->c[2] = (float) z;
1552  T->c[3] = (float) a;
1553  }
1554  return T;
1555 }
1556 float sfrotation_dist(struct SFRotation* A){
1557  //from a dif rotation, return the angle
1558  return A->c[4]; //just the angle?
1559 }
1560 int sfrotation_same(struct SFRotation *A, struct SFRotation *B){
1561  int i,isame = TRUE;
1562  for(i=0;i<4;i++)
1563  isame = isame && A->c[i] == B->c[i];
1564  return isame;
1565 }
1566 struct SFRotation *sfrotation_arr(struct SFRotation *A, int i){
1567  return &A[i];
1568 }
1569 struct SFRotation sfrotation_tmps[6];
1570 void *sfrotation_tmp [] = {&sfrotation_tmps[0],&sfrotation_tmps[1],&sfrotation_tmps[2],&sfrotation_tmps[3],&sfrotation_tmps[4],&sfrotation_tmps[5]};
1571 ftype ftype_sfrotation = {
1572  FIELDTYPE_SFRotation,
1573  VOIDFN sfrotation_copy,
1574  VOIDFN sfrotation_add,
1575  VOIDFN sfrotation_dif,
1576  VOIDFN sfrotation_scale,
1577  VOIDFN sfrotation_slerp,
1578  FLOATFN sfrotation_dist,
1579  INTFN sfrotation_same,
1580  INTFN sfrotation_same,
1581  VOIDFN sfrotation_arr,
1582  VOIDPTR sfrotation_tmp,
1583 };
1584 
1585 void do_OrientationChaserTick(void * ptr){
1586  double Now;
1587  struct X3D_OrientationChaser *_node = (struct X3D_OrientationChaser *)ptr;
1588  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr; //abstract interface
1589  if(!node) return;
1590  if(!_node->_buffer){
1591  chaser_ptrs *p = MALLOCN(node,sizeof(chaser_ptrs));
1592  _node->_buffer = REALLOCN(node,_node->_buffer,Buffer_length * sizeof(struct SFRotation)); //**changes with field type
1593  node->_t = &ftype_sfrotation; //**changes with field type
1594  node->_p = p;
1595  p->initialDestination = &_node->initialDestination;
1596  p->initialValue = &_node->initialValue;
1597  p->set_destination = &_node->set_destination;
1598  p->set_value = &_node->set_value;
1599  p->value_changed = &_node->value_changed;
1600  p->_buffer = _node->_buffer;
1601  p->_destination = &_node->_destination;
1602  p->_previousValue = &_node->_previousvalue;
1603  chaser_init(node);
1604  }
1605  Now = TickTime();
1606  if(NODE_NEEDS_COMPILING){
1607  chaser_ptrs *p = node->_p;
1608  ftype *t = node->_t;
1609  static int count = 0;
1610  node->isActive = TRUE;
1611  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
1612  //Q how to tell which set_ was set: set_destination or set_value?
1613  //if(!vecsame3f(node->set_destination.c,node->_destination.c))
1614  if(!t->same(p->set_destination,p->_destination))
1615  chaser_set_destination(node, Now);
1616  //else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
1617  else if(!t->same(p->set_value,p->initialValue))
1618  chaser_set_value(node);
1619  MARK_NODE_COMPILED
1620  count++;
1621  }
1622  if(node->isActive)
1623  chaser_tick(node,Now);
1624 }
1625 
1626 void do_OrientationDamperTick(void * ptr){
1627  struct X3D_OrientationDamper *_node = (struct X3D_OrientationDamper *)ptr;
1628  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr; //abstract type
1629  if(!node)return;
1630  if(!_node->_values){
1631  damper_ptrs *p = MALLOCN(node,sizeof(damper_ptrs));
1632  node->_t = &ftype_sfrotation; //**changes with field type
1633  node->_p = p;
1634  _node->_values = REALLOCN(node,_node->_values,5 * sizeof(struct SFRotation)); //**changes with field type
1635  p->initialDestination = &_node->initialDestination;
1636  p->initialValue = &_node->initialValue;
1637  p->set_destination = &_node->set_destination;
1638  p->set_value = &_node->set_value;
1639  p->value_changed = &_node->value_changed;
1640  p->_input = &_node->_input;
1641  p->_values = _node->_values;
1642  //damper_CheckInit(node);
1643  damper_Init(node);
1644  }
1645 
1646  if(NODE_NEEDS_COMPILING){
1647  //node->isActive = TRUE;
1648  damper_ptrs *p = node->_p;
1649  ftype *t = node->_t;
1650 
1651  //if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
1652  if(!t->same(p->set_destination,p->_input))
1653  //damper_set_destination(node, node->set_destination);
1654  damper_set_destination(node, p->set_destination);
1655  //set_tau
1656  if(node->tau != node->_tau)
1657  damper_set_tau(node,node->tau);
1658  //set_value
1659  //if(!vecsame3f(node->initialValue.c,node->set_value.c))
1660  if(!t->same(p->initialValue,p->set_value))
1661  //damper_set_value(node,node->set_value);
1662  damper_set_value(node,p->set_value);
1663  MARK_NODE_COMPILED
1664  }
1665  if(node->isActive)
1666  tick_damper(node,TickTime());
1667 }
1668 
1669 
1670 void do_OrientationChaserTick_default(void * ptr){
1671  struct X3D_OrientationChaser *node = (struct X3D_OrientationChaser *)ptr;
1672  if(!node)return;
1673  if(NODE_NEEDS_COMPILING){
1674  //default action copy input to output when not implemented
1675  veccopy3f(node->value_changed.c, node->set_destination.c);
1676  node->value_changed.c[3] = node->set_destination.c[3];
1677  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_OrientationChaser, value_changed));
1678  MARK_NODE_COMPILED
1679  }
1680 }
1681 void do_OrientationDamperTick_default(void * ptr){
1682  struct X3D_OrientationDamper *node = (struct X3D_OrientationDamper *)ptr;
1683  if(!node)return;
1684  if(NODE_NEEDS_COMPILING){
1685  //default action copy input to output when not implemented
1686  veccopy3f(node->value_changed.c, node->set_destination.c);
1687  node->value_changed.c[3] = node->set_destination.c[3];
1688  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_OrientationDamper, value_changed));
1689  MARK_NODE_COMPILED
1690  }
1691 }
1692 
1693 //>> orientation chaser old way works
1694 void orichaser_init(struct X3D_OrientationChaser *node)
1695 {
1696  int C;
1697  struct SFRotation *buffer = (struct SFRotation*)node->_buffer;
1698  node->_destination = node->initialDestination;
1699  buffer[0]= node->initialDestination; //initial_destination;
1700  for(C= 1; C<Buffer_length; C++ )
1701  buffer[C]= node->initialValue; //initial_value;
1702  node->_previousvalue= node->initialValue; //initial_value;
1703  node->_steptime= node->duration / (double) Buffer_length; //cNumSupports;
1704 }
1705 double orichaser_UpdateBuffer(struct X3D_OrientationChaser *node, double Now)
1706 {
1707  int C;
1708  double Frac;
1709  struct SFRotation *buffer = (struct SFRotation*)node->_buffer;
1710 
1711  Frac = (Now - node->_bufferendtime) / node->_steptime;
1712  // is normally < 1. When it has grown to be larger than 1, we have to shift the array because the step response
1713  // of the oldest entry has already reached its destination, and it's time for a newer entry.
1714  // has already reached it
1715  // In the case of a very low frame rate, or a very short cStepTime we may need to shift by more than one entry.
1716 
1717  if(Frac >= 1.0)
1718  {
1719  int NumToShift= (int)floor(Frac);
1720  Frac-= (double) NumToShift;
1721  if(NumToShift < Buffer_length)
1722  { // normal case.
1723 
1724  node->_previousvalue= buffer[Buffer_length - NumToShift];
1725  for( C= Buffer_length - 1; C>=NumToShift; C-- )
1726  buffer[C]= buffer[C - NumToShift];
1727  for( C= 0; C<NumToShift; C++ )
1728  {
1729  // Hmm, we have a destination value, but don't know how it has
1730  // reached the current state.
1731  // Therefore we do a linear interpolation from the latest value in the buffer to destination.
1732  float Alpha= (float)C / (float)NumToShift;
1733 
1734  //Buffer[C]= destination.slerp(Buffer[NumToShift], Alpha);
1735  if(1)sfrotation_slerp(&buffer[C],&node->_destination,&buffer[NumToShift],Alpha); //Q. order of slerp params?
1736  else sfrotation_slerp(&buffer[C],&buffer[NumToShift],&node->_destination,Alpha); //Q. order of slerp params?
1737  }
1738  }else
1739  {
1740  // degenerated case:
1741  //
1742  // We have a _VERY_ low frame rate...
1743  // we can only guess how we should fill the array.
1744  // Maybe we could write part of a linear interpolation
1745  // from Buffer[0] to destination, that goes from BufferEndTime to Now
1746  // (possibly only the end of the interpolation is to be written),
1747  // but if we rech here we are in a very degenerate case...
1748  // Thus we just write destination to the buffer.
1749  node->_previousvalue= NumToShift == Buffer_length? buffer[0] : node->_destination;
1750 
1751  for( C= 0; C<Buffer_length; C++ )
1752  buffer[C]= node->_destination;
1753  }
1754  node->_bufferendtime+= NumToShift * node->_steptime;
1755  }
1756  return Frac;
1757 }
1758 //when a route toNode.toField is PositionChaser.set_destination
1759 //we need to call this function (somehow) much like a script?
1760 //
1761 void orichaser_set_destination(struct X3D_OrientationChaser *node, struct SFRotation Dest, double Now)
1762 {
1763  node->_destination= Dest;
1764  // Somehow we assign to Buffer[-1] and wait untill this gets shifted into the real buffer.
1765  // Would we assign to Buffer[0] instead, we'd have no delay, but this would create a jump in the
1766  // output because Buffer[0] is associated with a value in the past.
1767  orichaser_UpdateBuffer(node, Now);
1768 }
1769 // This function defines the shape of how the output responds to the input.
1770 // It must accept values for T in the range 0 <= T <= 1.
1771 // In order to create a smooth animation, it should return 0 for T == 0,
1772 // 1 for T == 1 and be sufficient smooth in the range 0 <= T <= 1.
1773 
1774 // It should be optimized for speed, in order for high performance. It's
1775 // executed Buffer.length + 1 times each simulation tick.
1776 double orichaser_StepResponseCore(double T)
1777 {
1778  return .5 - .5 * cos(T * PI);
1779 }
1780 double orichaser_StepResponse(struct X3D_OrientationChaser *node, double t)
1781 {
1782  if(t < 0.0)
1783  return 0.0;
1784  if(t > node->duration)
1785  return 1.0;
1786  // When optimizing for speed, the above two if(.) cases can be omitted,
1787  // as this funciton will not be called for values outside of 0..duration.
1788  return orichaser_StepResponseCore(t / node->duration);
1789 }
1790 
1791 void orichaser_tick(struct X3D_OrientationChaser *node, double Now)
1792 {
1793  int C;
1794  double Frac, Alpha;
1795  struct SFRotation Output;
1796  struct SFRotation DeltaIn;
1797  //struct SFRotation DeltaOut;
1798  struct SFRotation tmp0; //, tmp1;
1799  struct SFRotation *buffer = (struct SFRotation*)node->_buffer;
1800 
1801  //orichaser_CheckInit(node);
1802  if(!node->_bufferendtime)
1803  {
1804  node->_bufferendtime= Now; // first event we received, so we are in the initialization phase.
1805  node->value_changed= node->initialValue; //initial_value;
1806  return;
1807  }
1808  Frac= orichaser_UpdateBuffer(node, Now);
1809  // Frac is a value in 0 <= Frac < 1.
1810 
1811  // Now we can calculate the output.
1812  // This means we calculate the delta between each entry in Buffer and its previous
1813  // entries, calculate the step response of each such step and add it to form the output.
1814 
1815  // The oldest vaule Buffer[Buffer.length - 1] needs some extra thought, because it has
1816  // no previous value. More exactly, we haven't stored a previous value anymore.
1817  // However, the step response of that missing previous value has already reached its
1818  // destination, so we can - would we have that previous value - use this as a start point
1819  // for adding the step responses.
1820  // Actually UpdateBuffer(.) maintains this value in
1821 
1822  //var Output= previousValue;
1823  Output= node->_previousvalue;
1824  //var DeltaIn= previousValue.inverse().multiply(Buffer[Buffer.length - 1]);
1825  if(0){
1826  sfrotation_inverse(&tmp0,&node->_previousvalue);
1827  sfrotation_multiply(&DeltaIn,&tmp0,&buffer[Buffer_length -1]);
1828  }else{
1829  sfrotation_dif(&DeltaIn,&buffer[Buffer_length -1],&node->_previousvalue); //A - B same as B.inverse x A
1830  }
1831 
1832  Alpha = orichaser_StepResponse(node,((double)Buffer_length - 1.0 + Frac) * node->_steptime);
1833  //Output= Output.slerp(Output.multiply(DeltaIn), StepResponse((Buffer.length - 1 + Frac) * cStepTime));
1834  if(0)
1835  sfrotation_multiply(&tmp0,&Output,&DeltaIn);
1836  else
1837  sfrotation_add(&tmp0,&Output,&DeltaIn); //same as multipley
1838 
1839  sfrotation_slerp(&Output,&Output,&tmp0,(float)Alpha);
1840  for(C= Buffer_length - 2; C>=0; C-- )
1841  {
1842  //var DeltaIn= Buffer[C + 1].inverse().multiply(Buffer[C]);
1843  if(0){
1844  sfrotation_inverse(&tmp0,&buffer[C + 1]);
1845  sfrotation_multiply(&DeltaIn,&tmp0,&buffer[C]);
1846  }else{
1847  sfrotation_dif(&DeltaIn,&buffer[C],&buffer[C+1]);
1848  }
1849  Alpha = orichaser_StepResponse(node,((float)C + Frac) * node->_steptime);
1850  //Output= Output.slerp(Output.multiply(DeltaIn), StepResponse((C + Frac) * cStepTime));
1851  if(0)
1852  sfrotation_multiply(&tmp0,&Output,&DeltaIn);
1853  else
1854  sfrotation_add(&tmp0,&Output,&DeltaIn);
1855 
1856  sfrotation_slerp(&Output,&Output,&tmp0,(float)Alpha); //order of slerp?
1857  }
1858  if(!sfrotation_same(&Output,&node->value_changed)){
1859  node->value_changed= Output;
1860  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_OrientationChaser, value_changed));
1861  }
1862 }
1863 void orichaser_set_value(struct X3D_OrientationChaser *node, struct SFRotation opos)
1864 {
1865  node->value_changed= opos;
1866  node->initialValue = opos;
1867  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_OrientationChaser, value_changed));
1868  node->isActive = TRUE;
1869  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_OrientationChaser, isActive));
1870 }
1871 
1872 
1873 void do_OrientationChaserTick_oldway_works(void * ptr){
1874  double Now;
1875  struct X3D_OrientationChaser *node = (struct X3D_OrientationChaser *)ptr;
1876  if(!node) return;
1877  if(!node->_buffer){
1878  node->_buffer = REALLOCN(node,node->_buffer,Buffer_length * sizeof(struct SFRotation));
1879  orichaser_init(node);
1880  }
1881  Now = TickTime();
1882  if(NODE_NEEDS_COMPILING){
1883  //printf("node_needs_compiling\n");
1884  node->isActive = TRUE;
1885  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_OrientationChaser, isActive));
1886  //Q how to tell which set_ was set: set_destination or set_value?
1887  if(!sfrotation_same(&node->set_destination,&node->_destination))
1888  orichaser_set_destination(node, node->set_destination,Now);
1889  else if(!sfrotation_same(&node->set_value,&node->initialValue)) //not sure I have the right idea here
1890  orichaser_set_value(node,node->set_value);
1891  MARK_NODE_COMPILED
1892  }
1893  if(node->isActive)
1894  orichaser_tick(node,Now);
1895 }
1896 
1897 //<<< oldway orientationchaser
1898 
1899 
1900 
1901 void do_CoordinateChaserTick(void * ptr){
1902  double Now;
1903  struct X3D_CoordinateChaser *_node = (struct X3D_CoordinateChaser *)ptr;
1904  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr; //abstract interface
1905  if(!node) return;
1906  if(!_node->_buffer){
1907  chaser_ptrs *p = MALLOCN(node,sizeof(chaser_ptrs));
1908  _node->_buffer = REALLOCN(node,_node->_buffer,Buffer_length * sizeof(struct Multi_Vec3f)); //**changes with field type
1909  node->_t = &ftype_mfvec3f; //**changes with field type
1910  node->_p = p;
1911  p->initialDestination = &_node->initialDestination;
1912  p->initialValue = &_node->initialValue;
1913  p->set_destination = &_node->set_destination;
1914  p->set_value = &_node->set_value;
1915  p->value_changed = &_node->value_changed;
1916  p->_buffer = _node->_buffer;
1917  p->_destination = &_node->_destination;
1918  p->_previousValue = &_node->_previousvalue;
1919  chaser_init(node);
1920  }
1921  Now = TickTime();
1922  if(NODE_NEEDS_COMPILING){
1923  chaser_ptrs *p = node->_p;
1924  ftype *t = node->_t;
1925 
1926  node->isActive = TRUE;
1927  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
1928  //Q how to tell which set_ was set: set_destination or set_value?
1929  //if(!vecsame3f(node->set_destination.c,node->_destination.c))
1930  if(!t->same(p->set_destination,p->_destination))
1931  chaser_set_destination(node, Now);
1932  //else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
1933  else if(!t->same(p->set_value,p->initialValue))
1934  chaser_set_value(node);
1935  MARK_NODE_COMPILED
1936  }
1937  if(node->isActive)
1938  chaser_tick(node,Now);
1939 }
1940 
1941 void do_CoordinateDamperTick(void * ptr){
1942  struct X3D_CoordinateDamper *_node = (struct X3D_CoordinateDamper *)ptr;
1943  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr; //abstract type
1944  if(!node)return;
1945  if(!_node->_values){
1946  damper_ptrs *p = MALLOCN(node,sizeof(damper_ptrs));
1947  node->_t = &ftype_sfvec3f; //**changes with field type
1948  node->_p = p;
1949  _node->_values = REALLOCN(node,_node->_values,5 * sizeof(struct Multi_Vec3f)); //**changes with field type
1950  p->initialDestination = &_node->initialDestination;
1951  p->initialValue = &_node->initialValue;
1952  p->set_destination = &_node->set_destination;
1953  p->set_value = &_node->set_value;
1954  p->value_changed = &_node->value_changed;
1955  p->_input = &_node->_input;
1956  p->_values = _node->_values;
1957  //damper_CheckInit(node);
1958  damper_Init(node);
1959  }
1960 
1961  if(NODE_NEEDS_COMPILING){
1962  //node->isActive = TRUE;
1963  damper_ptrs *p = node->_p;
1964  ftype *t = node->_t;
1965 
1966  //if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
1967  if(!t->same(p->set_destination,p->_input))
1968  //damper_set_destination(node, node->set_destination);
1969  damper_set_destination(node, p->set_destination);
1970  //set_tau
1971  if(node->tau != node->_tau)
1972  damper_set_tau(node,node->tau);
1973  //set_value
1974  //if(!vecsame3f(node->initialValue.c,node->set_value.c))
1975  if(!t->same(p->initialValue,p->set_value))
1976  //damper_set_value(node,node->set_value);
1977  damper_set_value(node,p->set_value);
1978  MARK_NODE_COMPILED
1979  }
1980  if(node->isActive)
1981  tick_damper(node,TickTime());
1982 }
1983 
1984 
1985 
1986 
1987 
1988 void do_PositionChaser2DTick_default(void * ptr){
1989  struct X3D_PositionChaser2D *node = (struct X3D_PositionChaser2D *)ptr;
1990  if(!node)return;
1991  if(NODE_NEEDS_COMPILING){
1992  //default action copy input to output when not implemented
1993  veccopy2f(node->value_changed.c, node->set_destination.c);
1994  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser2D, value_changed));
1995  MARK_NODE_COMPILED
1996  }
1997 
1998 }
1999 void do_PositionDamper2DTick_default(void * ptr){
2000  struct X3D_PositionDamper2D *node = (struct X3D_PositionDamper2D *)ptr;
2001  if(!node)return;
2002  if(NODE_NEEDS_COMPILING){
2003  //default action copy input to output when not implemented
2004  veccopy2f(node->value_changed.c, node->set_destination.c);
2005  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionDamper2D, value_changed));
2006  MARK_NODE_COMPILED
2007  }
2008 
2009 }
2010 float *veclerp2f(float *T, float *A, float *B, float alpha){
2011  int i;
2012  for(i=0;i<2;i++){
2013  T[i] = (1.0f - alpha)*A[i] + alpha*B[i];
2014  }
2015  return T;
2016 }
2017 struct SFVec2f *sfvec2f_copy(struct SFVec2f* T, struct SFVec2f *A){
2018  veccopy2f(T->c,A->c);
2019  return T;
2020 }
2021 struct SFVec2f *sfvec2f_add(struct SFVec2f* T, struct SFVec2f *A, struct SFVec2f *B){
2022  vecadd2f(T->c,A->c,B->c);
2023  return T;
2024 }
2025 struct SFVec2f *sfvec2f_dif(struct SFVec2f* T, struct SFVec2f *A, struct SFVec2f *B){
2026  vecdif2f(T->c,A->c,B->c);
2027  return T;
2028 }
2029 struct SFVec2f *sfvec2f_scale(struct SFVec2f* T, struct SFVec2f *A, float S){
2030  vecscale2f(T->c,A->c,S);
2031  return T;
2032 }
2033 struct SFVec2f *sfvec2f_lerp(struct SFVec2f* T, struct SFVec2f *A, struct SFVec2f *B, float alpha){
2034  veclerp2f(T->c,A->c,B->c,alpha);
2035  return T;
2036 }
2037 float sfvec2f_dist(struct SFVec2f* A){
2038  return veclength2f(A->c);
2039 }
2040 int sfvec2f_same(struct SFVec2f *A, struct SFVec2f *B){
2041  return vecsame2f(A->c,B->c);
2042 }
2043 struct SFVec2f *sfvec2f_arr(struct SFVec2f *A, int i){
2044  return &A[i];
2045 }
2046 struct SFVec2f sfvec2f_tmps[6];
2047 void *sfvec2f_tmp [] = {&sfvec2f_tmps[0],&sfvec2f_tmps[1],&sfvec2f_tmps[2],&sfvec2f_tmps[3],&sfvec2f_tmps[4],&sfvec2f_tmps[5]};
2048 ftype ftype_sfvec2f = {
2049  FIELDTYPE_SFVec2f,
2050  VOIDFN sfvec2f_copy,
2051  VOIDFN sfvec2f_add,
2052  VOIDFN sfvec2f_dif,
2053  VOIDFN sfvec2f_scale,
2054  VOIDFN sfvec2f_lerp,
2055  FLOATFN sfvec2f_dist,
2056  INTFN sfvec2f_same,
2057  INTFN sfvec2f_same,
2058  VOIDFN sfvec2f_arr,
2059  VOIDPTR sfvec2f_tmp,
2060 };
2061 
2062 void do_PositionChaser2DTick(void * ptr){
2063  double Now;
2064  struct X3D_PositionChaser2D *_node = (struct X3D_PositionChaser2D *)ptr;
2065  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr; //abstract interface
2066  if(!node) return;
2067  if(!_node->_buffer){
2068  chaser_ptrs *p = MALLOCN(node,sizeof(chaser_ptrs));
2069  _node->_buffer = REALLOCN(node,_node->_buffer,Buffer_length * sizeof(struct SFVec2f)); //**changes with ftype
2070  node->_t = &ftype_sfvec2f; //***changes with ftype
2071  node->_p = p;
2072  p->initialDestination = &_node->initialDestination;
2073  p->initialValue = &_node->initialValue;
2074  p->set_destination = &_node->set_destination;
2075  p->set_value = &_node->set_value;
2076  p->value_changed = &_node->value_changed;
2077  p->_buffer = _node->_buffer;
2078  p->_destination = &_node->_destination;
2079  p->_previousValue = &_node->_previousvalue;
2080  chaser_init(node);
2081  }
2082  Now = TickTime();
2083  if(NODE_NEEDS_COMPILING){
2084  chaser_ptrs *p = node->_p;
2085  ftype *t = node->_t;
2086 
2087  node->isActive = TRUE;
2088  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
2089  //Q how to tell which set_ was set: set_destination or set_value?
2090  //if(!vecsame3f(node->set_destination.c,node->_destination.c))
2091  if(!t->same(p->set_destination,p->_destination))
2092  chaser_set_destination(node, Now);
2093  //else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
2094  else if(!t->same(p->set_value,p->initialValue))
2095  chaser_set_value(node);
2096  MARK_NODE_COMPILED
2097  }
2098  if(node->isActive)
2099  chaser_tick(node,Now);
2100 }
2101 void do_PositionDamper2DTick(void * ptr){
2102  struct X3D_PositionDamper2D *_node = (struct X3D_PositionDamper2D *)ptr;
2103  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr; //abstract type
2104  if(!node)return;
2105  if(!_node->_values){
2106  damper_ptrs *p = MALLOCN(node,sizeof(damper_ptrs));
2107  node->_t = &ftype_sfvec2f; //** changes with ftype
2108  node->_p = p;
2109  _node->_values = REALLOCN(node,_node->_values,5 * sizeof(struct SFVec2f)); //** changes with ftype
2110  p->initialDestination = &_node->initialDestination;
2111  p->initialValue = &_node->initialValue;
2112  p->set_destination = &_node->set_destination;
2113  p->set_value = &_node->set_value;
2114  p->value_changed = &_node->value_changed;
2115  p->_input = &_node->_input;
2116  p->_values = _node->_values;
2117  //damper_CheckInit(node);
2118  damper_Init(node);
2119  }
2120 
2121  if(NODE_NEEDS_COMPILING){
2122  //node->isActive = TRUE;
2123  damper_ptrs *p = node->_p;
2124  ftype *t = node->_t;
2125 
2126  //if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
2127  if(!t->same(p->set_destination,p->_input))
2128  //damper_set_destination(node, node->set_destination);
2129  damper_set_destination(node, p->set_destination);
2130  //set_tau
2131  if(node->tau != node->_tau)
2132  damper_set_tau(node,node->tau);
2133  //set_value
2134  //if(!vecsame3f(node->initialValue.c,node->set_value.c))
2135  if(!t->same(p->initialValue,p->set_value))
2136  //damper_set_value(node,node->set_value);
2137  damper_set_value(node,p->set_value);
2138  MARK_NODE_COMPILED
2139  }
2140  if(node->isActive)
2141  tick_damper(node,TickTime());
2142 }
2143 
2144 
2145 void do_ScalarChaserTick_default(void * ptr){
2146  struct X3D_ScalarChaser *node = (struct X3D_ScalarChaser *)ptr;
2147  if(!node)return;
2148  if(NODE_NEEDS_COMPILING){
2149  //default action copy input to output when not implemented
2150  node->value_changed = node->set_destination;
2151  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_ScalarChaser, value_changed));
2152  MARK_NODE_COMPILED
2153  }
2154 }
2155 void do_ScalarDamperTick_default(void * ptr){
2156  struct X3D_ScalarDamper *node = (struct X3D_ScalarDamper *)ptr;
2157  if(!node)return;
2158  if(NODE_NEEDS_COMPILING){
2159  //default action copy input to output when not implemented
2160  node->value_changed = node->set_destination;
2161  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_ScalarDamper, value_changed));
2162  MARK_NODE_COMPILED
2163  }
2164 }
2165 float *scalar_copy(float* T, float *A){
2166  *T = *A;
2167  return T;
2168 }
2169 float *scalar_add(float* T, float *A, float *B){
2170  *T = *A + *B;
2171  return T;
2172 }
2173 float *scalar_dif(float* T, float *A, float *B){
2174  *T = *A - *B;
2175  return T;
2176 }
2177 float *scalar_scale(float* T, float *A, float S){
2178  *T = *A *S;
2179  return T;
2180 }
2181 float *scalar_lerp(float* T, float *A, float *B, float alpha){
2182  *T = (1.0f -alpha)*(*A) + alpha*(*B);
2183  return T;
2184 }
2185 float scalar_dist(float* A){
2186  return (float)fabs(*A);
2187 }
2188 int scalar_same(float *A, float *B){
2189  return *A == *B ? TRUE : FALSE;
2190 }
2191 float *scalar_arr(float *A, int i){
2192  return &A[i];
2193 }
2194 float scalar_tmps[6];
2195 void *scalar_tmp [] = {&scalar_tmps[0],&scalar_tmps[1],&scalar_tmps[2],&scalar_tmps[3],&scalar_tmps[4],&scalar_tmps[5]};
2196 ftype ftype_scalar = {
2197  FIELDTYPE_SFFloat,
2198  VOIDFN scalar_copy,
2199  VOIDFN scalar_add,
2200  VOIDFN scalar_dif,
2201  VOIDFN scalar_scale,
2202  VOIDFN scalar_lerp,
2203  FLOATFN scalar_dist,
2204  INTFN scalar_same,
2205  INTFN scalar_same,
2206  VOIDFN scalar_arr,
2207  VOIDPTR scalar_tmp,
2208 };
2209 
2210 void do_ScalarChaserTick(void * ptr){
2211  double Now;
2212  struct X3D_ScalarChaser *_node = (struct X3D_ScalarChaser *)ptr;
2213  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr; //abstract interface
2214  if(!node) return;
2215  if(!_node->_buffer){
2216  chaser_ptrs *p = MALLOCN(node,sizeof(chaser_ptrs));
2217  _node->_buffer = REALLOCN(node,_node->_buffer,Buffer_length * sizeof(float)); //**changes with ftype
2218  node->_t = &ftype_scalar; //***changes with ftype
2219  node->_p = p;
2220  p->initialDestination = &_node->initialDestination;
2221  p->initialValue = &_node->initialValue;
2222  p->set_destination = &_node->set_destination;
2223  p->set_value = &_node->set_value;
2224  p->value_changed = &_node->value_changed;
2225  p->_buffer = _node->_buffer;
2226  p->_destination = &_node->_destination;
2227  p->_previousValue = &_node->_previousvalue;
2228  chaser_init(node);
2229  }
2230  Now = TickTime();
2231  if(NODE_NEEDS_COMPILING){
2232  chaser_ptrs *p = node->_p;
2233  ftype *t = node->_t;
2234 
2235  node->isActive = TRUE;
2236  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
2237  //Q how to tell which set_ was set: set_destination or set_value?
2238  //if(!vecsame3f(node->set_destination.c,node->_destination.c))
2239  if(!t->same(p->set_destination,p->_destination))
2240  chaser_set_destination(node, Now);
2241  //else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
2242  else if(!t->same(p->set_value,p->initialValue))
2243  chaser_set_value(node);
2244  MARK_NODE_COMPILED
2245  }
2246  if(node->isActive)
2247  chaser_tick(node,Now);
2248 }
2249 void do_ScalarDamperTick(void * ptr){
2250  struct X3D_ScalarDamper *_node = (struct X3D_ScalarDamper *)ptr;
2251  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr; //abstract type
2252  if(!node)return;
2253  if(!_node->_values){
2254  damper_ptrs *p = MALLOCN(node,sizeof(damper_ptrs));
2255  node->_t = &ftype_scalar; //** changes with ftype
2256  node->_p = p;
2257  _node->_values = REALLOCN(node,_node->_values,5 * sizeof(float)); //** changes with ftype
2258  p->initialDestination = &_node->initialDestination;
2259  p->initialValue = &_node->initialValue;
2260  p->set_destination = &_node->set_destination;
2261  p->set_value = &_node->set_value;
2262  p->value_changed = &_node->value_changed;
2263  p->_input = &_node->_input;
2264  p->_values = _node->_values;
2265  //damper_CheckInit(node);
2266  damper_Init(node);
2267  }
2268 
2269  if(NODE_NEEDS_COMPILING){
2270  //node->isActive = TRUE;
2271  damper_ptrs *p = node->_p;
2272  ftype *t = node->_t;
2273 
2274  //if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
2275  if(!t->same(p->set_destination,p->_input))
2276  //damper_set_destination(node, node->set_destination);
2277  damper_set_destination(node, p->set_destination);
2278  //set_tau
2279  if(node->tau != node->_tau)
2280  damper_set_tau(node,node->tau);
2281  //set_value
2282  //if(!vecsame3f(node->initialValue.c,node->set_value.c))
2283  if(!t->same(p->initialValue,p->set_value))
2284  //damper_set_value(node,node->set_value);
2285  damper_set_value(node,p->set_value);
2286  MARK_NODE_COMPILED
2287  }
2288  if(node->isActive)
2289  tick_damper(node,TickTime());
2290 }
2291 
2292 void do_TexCoordChaser2DTick_default(void * ptr){
2293  struct X3D_TexCoordChaser2D *node = (struct X3D_TexCoordChaser2D *)ptr;
2294  if(!node)return;
2295  if(NODE_NEEDS_COMPILING){
2296  //default action copy input to output when not implemented
2297  int n;
2298  n = node->set_destination.n;
2299  node->value_changed.n = n;
2300  node->value_changed.p = REALLOC(node->value_changed.p,n * sizeof(struct SFVec2f));
2301  memcpy(node->value_changed.p,node->set_destination.p,n*sizeof(struct SFVec2f));
2302  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_TexCoordChaser2D, value_changed));
2303  MARK_NODE_COMPILED
2304  }
2305 }
2306 void do_TexCoordDamper2DTick_default(void * ptr){
2307  struct X3D_TexCoordDamper2D *node = (struct X3D_TexCoordDamper2D *)ptr;
2308  if(!node)return;
2309  if(NODE_NEEDS_COMPILING){
2310  //default action copy input to output when not implemented
2311  int n;
2312  n = node->set_destination.n;
2313  node->value_changed.n = n;
2314  node->value_changed.p = REALLOC(node->value_changed.p,n * sizeof(struct SFVec2f));
2315  memcpy(node->value_changed.p,node->set_destination.p,n*sizeof(struct SFVec2f));
2316  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_TexCoordDamper2D, value_changed));
2317  MARK_NODE_COMPILED
2318  }
2319 }
2320 
2321 struct Multi_Vec2f *mfvec2f_copy(struct Multi_Vec2f* T, struct Multi_Vec2f *A){
2322  T->p = REALLOC(T->p,A->n * sizeof(struct SFVec2f));
2323  T->n = A->n;
2324  memcpy(T->p,A->p,A->n * sizeof(struct SFVec2f));
2325  return T;
2326 }
2327 struct Multi_Vec2f *mfvec2f_add(struct Multi_Vec2f* T, struct Multi_Vec2f *A, struct Multi_Vec2f *B){
2328  int i;
2329  T->n = min(A->n,B->n);
2330  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec2f));
2331  for(i=0;i<T->n;i++)
2332  sfvec2f_add(&T->p[i],&A->p[i],&B->p[i]);
2333  return T;
2334 }
2335 struct Multi_Vec2f *mfvec2f_dif(struct Multi_Vec2f* T, struct Multi_Vec2f *A, struct Multi_Vec2f *B){
2336  int i;
2337  T->n = min(A->n,B->n);
2338  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec2f));
2339  for(i=0;i<T->n;i++)
2340  sfvec2f_dif(&T->p[i],&A->p[i],&B->p[i]);
2341  return T;
2342 }
2343 struct Multi_Vec2f *mfvec2f_scale(struct Multi_Vec2f* T, struct Multi_Vec2f *A, float S){
2344  int i;
2345  T->n = A->n;
2346  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec2f));
2347  for(i=0;i<T->n;i++)
2348  sfvec2f_scale(&T->p[i],&A->p[i],S);
2349  return T;
2350 }
2351 struct Multi_Vec2f *mfvec2f_lerp(struct Multi_Vec2f* T, struct Multi_Vec2f *A, struct Multi_Vec2f *B, float alpha){
2352  int i;
2353  T->n = min(A->n,B->n);
2354  T->p = REALLOC(T->p,T->n * sizeof(struct SFVec2f));
2355  for(i=0;i<T->n;i++)
2356  sfvec2f_lerp(&T->p[i],&A->p[i],&B->p[i],alpha);
2357  return T;
2358 }
2359 
2360 float mfvec2f_dist(struct Multi_Vec2f* A){
2361  int i;
2362  float dist = 0.0f;
2363  for(i=0;i<A->n;i++)
2364  dist += sfvec2f_dist(&A->p[i]);
2365  return dist;
2366 }
2367 int mfvec2f_same(struct Multi_Vec2f *A, struct Multi_Vec2f *B){
2368  int i, isame;
2369  if(A->n != B->n) return FALSE;
2370  isame = TRUE;
2371  for(i=0;i<A->n;i++)
2372  isame = isame && sfvec2f_same(&A->p[i],&B->p[i]);
2373  return isame;
2374 }
2375 struct Multi_Vec2f *mfvec2f_arr(struct Multi_Vec2f *A, int i){
2376  return &A[i];
2377 }
2378 struct Multi_Vec2f mfvec2f_tmps[6];
2379 void *mfvec2f_tmp [] = {&mfvec2f_tmps[0],&mfvec2f_tmps[1],&mfvec2f_tmps[2],&mfvec2f_tmps[3],&mfvec2f_tmps[4],&mfvec2f_tmps[5]};
2380 ftype ftype_mfvec2f = {
2381  FIELDTYPE_MFVec2f,
2382  VOIDFN mfvec2f_copy,
2383  VOIDFN mfvec2f_add,
2384  VOIDFN mfvec2f_dif,
2385  VOIDFN mfvec2f_scale,
2386  VOIDFN mfvec2f_lerp,
2387  FLOATFN mfvec2f_dist,
2388  INTFN mfvec2f_same,
2389  INTFN mfvec2f_same,
2390  VOIDFN mfvec2f_arr,
2391  VOIDPTR mfvec2f_tmp,
2392 };
2393 void do_TexCoordChaser2DTick(void * ptr){
2394  double Now;
2395  struct X3D_TexCoordChaser2D * _node = (struct X3D_TexCoordChaser2D *)ptr;
2396  struct X3D_PositionChaser *node = (struct X3D_PositionChaser *)ptr; //abstract interface
2397  if(!node) return;
2398  if(!_node->_buffer){
2399  chaser_ptrs *p = MALLOCN(node,sizeof(chaser_ptrs));
2400  _node->_buffer = REALLOCN(node,_node->_buffer,Buffer_length * sizeof(struct Multi_Vec2f)); //**changes with field type
2401  node->_t = &ftype_mfvec2f; //**changes with field type
2402  node->_p = p;
2403  p->initialDestination = &_node->initialDestination;
2404  p->initialValue = &_node->initialValue;
2405  p->set_destination = &_node->set_destination;
2406  p->set_value = &_node->set_value;
2407  p->value_changed = &_node->value_changed;
2408  p->_buffer = _node->_buffer;
2409  p->_destination = &_node->_destination;
2410  p->_previousValue = &_node->_previousvalue;
2411  chaser_init(node);
2412  }
2413  Now = TickTime();
2414  if(NODE_NEEDS_COMPILING){
2415  chaser_ptrs *p = node->_p;
2416  ftype *t = node->_t;
2417 
2418  node->isActive = TRUE;
2419  MARK_EVENT ((struct X3D_Node*)node, offsetof(struct X3D_PositionChaser, isActive));
2420  //Q how to tell which set_ was set: set_destination or set_value?
2421  //if(!vecsame3f(node->set_destination.c,node->_destination.c))
2422  if(!t->same(p->set_destination,p->_destination))
2423  chaser_set_destination(node, Now);
2424  //else if(!vecsame3f(node->set_value.c,node->initialValue.c)) //not sure I have the right idea here
2425  else if(!t->same(p->set_value,p->initialValue))
2426  chaser_set_value(node);
2427  MARK_NODE_COMPILED
2428  }
2429  if(node->isActive)
2430  chaser_tick(node,Now);
2431 }
2432 
2433 void do_TexCoordDamper2DTick(void * ptr){
2434  struct X3D_TexCoordDamper2D *_node = (struct X3D_TexCoordDamper2D *)ptr;
2435  struct X3D_PositionDamper *node = (struct X3D_PositionDamper *)ptr; //abstract type
2436  if(!node)return;
2437  if(!_node->_values){
2438  damper_ptrs *p = MALLOCN(node,sizeof(damper_ptrs));
2439  node->_t = &ftype_sfvec2f; //**changes with field type
2440  node->_p = p;
2441  _node->_values = REALLOCN(node,_node->_values,5 * sizeof(struct Multi_Vec2f)); //**changes with field type
2442  p->initialDestination = &_node->initialDestination;
2443  p->initialValue = &_node->initialValue;
2444  p->set_destination = &_node->set_destination;
2445  p->set_value = &_node->set_value;
2446  p->value_changed = &_node->value_changed;
2447  p->_input = &_node->_input;
2448  p->_values = _node->_values;
2449  //damper_CheckInit(node);
2450  damper_Init(node);
2451  }
2452 
2453  if(NODE_NEEDS_COMPILING){
2454  //node->isActive = TRUE;
2455  damper_ptrs *p = node->_p;
2456  ftype *t = node->_t;
2457 
2458  //if(!vecsame3f(node->set_destination.c,node->_input.c)) //not sure i have the right idea
2459  if(!t->same(p->set_destination,p->_input))
2460  //damper_set_destination(node, node->set_destination);
2461  damper_set_destination(node, p->set_destination);
2462  //set_tau
2463  if(node->tau != node->_tau)
2464  damper_set_tau(node,node->tau);
2465  //set_value
2466  //if(!vecsame3f(node->initialValue.c,node->set_value.c))
2467  if(!t->same(p->initialValue,p->set_value))
2468  //damper_set_value(node,node->set_value);
2469  damper_set_value(node,p->set_value);
2470  MARK_NODE_COMPILED
2471  }
2472  if(node->isActive)
2473  tick_damper(node,TickTime());
2474 }
2475 //============================
2476 
2477