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