/
linearframe.h
146 lines (118 loc) · 2.58 KB
/
linearframe.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#ifndef _LINEARFRAME_H
#define _LINEARFRAME_H
#include "mathvector.h"
#include "joeserialize.h"
#include "macros.h"
//#define EULER
//#define NSV
//#define VELOCITYVERLET
#define SUVAT
template <typename T>
class LINEARFRAME
{
friend class joeserialize::Serializer;
public:
LINEARFRAME() :
force(0),
inverse_mass(1.0),
halfstep(false)
{
}
const MATHVECTOR <T, 3> & GetForce() const
{
return force;
}
const MATHVECTOR <T, 3> GetVelocity() const
{
return GetVelocityFromMomentum(momentum);
}
const MATHVECTOR <T, 3> & GetPosition() const
{
return position;
}
const T GetMass() const
{
return 1.0 / inverse_mass;
}
const T GetInvMass() const
{
return inverse_mass;
}
/// this must only be called between integrate1 and integrate2 steps
void ApplyForce(const MATHVECTOR <T, 3> & f)
{
assert(halfstep);
force = force + f;
}
/// this must only be called between integrate1 and integrate2 steps
void SetForce(const MATHVECTOR <T, 3> & f)
{
assert(halfstep);
force = f;
}
void SetVelocity(const MATHVECTOR <T, 3> & velocity)
{
momentum = velocity / inverse_mass;
}
void SetPosition(const MATHVECTOR <T, 3> & newpos)
{
position = newpos;
}
void SetMass(const T & mass)
{
inverse_mass = 1.0 / mass;
}
/// both steps must be executed each frame and forces can only be set between steps 1 and 2
void Integrate1(const T & dt)
{
assert(!halfstep);
#ifdef VELOCITYVERLET
momentum = momentum + force * dt * 0.5;
position = position + momentum * inverse_mass * dt;
#endif
force.Set(0.0);
halfstep = true;
}
/// both steps must be executed each frame and forces must be set between steps 1 and 2
void Integrate2(const T & dt)
{
assert(halfstep);
#ifdef VELOCITYVERLET
momentum = momentum + force * dt * 0.5;
#endif
#ifdef NSV
momentum = momentum + force * dt;
position = position + momentum * inverse_mass * dt;
#endif
#ifdef EULER
position = position + momentum * inverse_mass * dt;
momentum = momentum + force * dt;
#endif
#ifdef SUVAT
position = position + momentum * inverse_mass * dt + force * inverse_mass * dt * dt * 0.5;
momentum = momentum + force * dt;
#endif
halfstep = false;
}
bool Serialize(joeserialize::Serializer & s)
{
_SERIALIZE_(s, position);
_SERIALIZE_(s, momentum);
_SERIALIZE_(s, force);
return true;
}
private:
//primary
MATHVECTOR <T, 3> position;
MATHVECTOR <T, 3> momentum;
MATHVECTOR <T, 3> force;
//constants
T inverse_mass;
//housekeeping
bool halfstep;
MATHVECTOR <T, 3> GetVelocityFromMomentum(const MATHVECTOR <T, 3> & moment) const
{
return moment * inverse_mass;
}
};
#endif