Vuo  2.3.2
VuoSmooth.h
Go to the documentation of this file.
1 
10 #if (defined(type) && defined(zeroValue) && defined(add) && defined(subtract) && defined(multiply) && defined(bezier3)) || defined(DOXYGEN)
11 
15 typedef struct _VuoSmoothInertia
16 {
17  bool moving;
18  bool updateNeededAfterSetPosition;
19  type positionLastFrame;
20  type velocity;
21  type target;
22  type positionWhenTargetChanged;
23  type velocityWhenTargetChanged;
24  VuoReal timeLastFrame;
25  VuoReal timeWhenTargetChanged;
26  VuoReal duration;
28 
32 static VuoSmoothInertia VuoSmoothInertia_make(type initialPosition)
33 {
34  VuoSmoothInertia s = (VuoSmoothInertia)calloc(1,sizeof(struct _VuoSmoothInertia));
35  VuoRegister(s, free);
36  s->positionLastFrame = initialPosition;
37  return s;
38 }
39 
43 static void VuoSmoothInertia_setPosition(VuoSmoothInertia s, type position)
44 {
45  s->positionLastFrame = position;
46  s->moving = false;
47  s->velocity = zeroValue;
48  s->updateNeededAfterSetPosition = true;
49 }
50 
54 static void VuoSmoothInertia_setTarget(VuoSmoothInertia s, VuoReal time, type target)
55 {
56  s->target = target;
57  s->positionWhenTargetChanged = s->positionLastFrame;
58  s->velocityWhenTargetChanged = s->velocity;
59  s->timeWhenTargetChanged = time;
60  s->moving = true;
61 }
62 
67 {
68  s->duration = MAX(duration, 0.00001);
69 }
70 
78 static bool VuoSmoothInertia_step(VuoSmoothInertia s, VuoReal time, type *calculatedPosition)
79 {
80  bool movedDuringThisStep = false;
81 
82  if (s->updateNeededAfterSetPosition)
83  {
84  movedDuringThisStep = true;
85  *calculatedPosition = s->positionLastFrame;
86  s->updateNeededAfterSetPosition = false;
87  }
88 
89  if (s->moving)
90  {
91  movedDuringThisStep = true;
92  VuoReal timeSinceLastFrame = time - s->timeLastFrame;
93  if (timeSinceLastFrame != 0)
94  {
95  double timeSinceTargetChanged = MIN(time - s->timeWhenTargetChanged, s->duration);
96  double curviness = s->duration/(3.*timeSinceLastFrame);
97  type p1 = add(s->positionWhenTargetChanged, multiply(s->velocityWhenTargetChanged, timeSinceLastFrame*curviness));
98  *calculatedPosition = bezier3(s->positionWhenTargetChanged, p1, s->target, s->target, timeSinceTargetChanged/s->duration);
99 
100  s->velocity = multiply(subtract(*calculatedPosition, s->positionLastFrame), 1./timeSinceLastFrame);
101  s->positionLastFrame = *calculatedPosition;
102 
103  if (time - s->timeWhenTargetChanged > s->duration)
104  {
105  s->moving = false;
106  s->velocity = zeroValue;
107  }
108  }
109  }
110 
111  s->timeLastFrame = time;
112 
113  return movedDuringThisStep;
114 }
115 
116 #endif