naev 0.10.4
physics.c
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
5#include <stdio.h>
6#include <stdlib.h>
7
8#include "naev.h"
11#include "log.h"
12#include "nstring.h"
13#include "physics.h"
14
15/*
16 * M I S C
17 */
18static double angle_cleanup( double a )
19{
20 if (FABS(a) >= 2.*M_PI) {
21 double na = fmod(a, 2.*M_PI);
22 if (a < 0.)
23 na += 2.*M_PI;
24 return na;
25 }
26 return a;
27}
34double angle_diff( double ref, double a )
35{
36 /* Get angles. */
37 double a1 = angle_cleanup(ref);
38 double a2 = angle_cleanup(a);
39 double d = a2 - a1;
40
41 /* Filter offsets. */
42 d = (d < M_PI) ? d : d - 2.*M_PI;
43 d = (d > -M_PI) ? d : d + 2.*M_PI;
44 return d;
45}
46
62static void solid_update_euler( Solid *obj, double dt )
63{
64 double px,py, vx,vy, ax,ay, th;
65 double cdir, sdir;
66
67 /* make sure angle doesn't flip */
68 obj->dir += obj->dir_vel*dt;
69 if (obj->dir >= 2*M_PI)
70 obj->dir -= 2*M_PI;
71 if (obj->dir < 0.)
72 obj->dir += 2*M_PI;
73
74 /* Initial positions. */
75 px = obj->pos.x;
76 py = obj->pos.y;
77 vx = obj->vel.x;
78 vy = obj->vel.y;
79 th = obj->thrust;
80
81 /* Save direction. */
82 sdir = sin(obj->dir);
83 cdir = cos(obj->dir);
84
85 /* Get acceleration. */
86 ax = th*cdir / obj->mass;
87 ay = th*sdir / obj->mass;
88
89 /* Symplectic Euler */
90 vx += ax*dt;
91 vy += ay*dt;
92 px += vx*dt;
93 py += vy*dt;
94
95 /* Update position and velocity. */
96 vec2_cset( &obj->vel, vx, vy );
97 vec2_cset( &obj->pos, px, py );
98}
99
123#define RK4_MIN_H 0.01
124static void solid_update_rk4( Solid *obj, double dt )
125{
126 int N; /* for iteration, and pass calculation */
127 double h, px,py, vx,vy; /* pass, and position/velocity values */
128 double ix,iy, tx,ty, th; /* initial and temporary cartesian vector values */
129 double vmod, vang;
130 int vint;
131 int limit; /* limit speed? */
132
133 /* Initial positions and velocity. */
134 px = obj->pos.x;
135 py = obj->pos.y;
136 vx = obj->vel.x;
137 vy = obj->vel.y;
138 limit = (obj->speed_max >= 0.);
139
140 /* Initial RK parameters. */
141 if (dt > RK4_MIN_H)
142 N = (int)(dt / RK4_MIN_H);
143 else
144 N = 1;
145 vmod = MOD( vx, vy );
146 vint = (int) vmod/100.;
147 if (N < vint)
148 N = vint;
149 h = dt / (double)N; /* step */
150
151 /* Movement Quantity Theorem: m*a = \sum f */
152 th = obj->thrust / obj->mass;
153
154 for (int i=0; i < N; i++) { /* iterations */
155 /* Calculate acceleration for the frame. */
156 double ax = th*cos(obj->dir);
157 double ay = th*sin(obj->dir);
158
159 /* Limit the speed. */
160 if (limit) {
161 vmod = MOD( vx, vy );
162 if (vmod > obj->speed_max) {
163 /* We limit by applying a force against it. */
164 vang = ANGLE( vx, vy ) + M_PI;
165 vmod = 3. * (vmod - obj->speed_max);
166
167 /* Update accel. */
168 ax += vmod * cos(vang);
169 ay += vmod * sin(vang);
170 }
171 }
172
173 /* x component */
174 tx = ix = ax;
175 tx += 2.*ix + h*tx;
176 tx += 2.*ix + h*tx;
177 tx += ix + h*tx;
178 tx *= h/6.;
179
180 vx += tx;
181 px += vx * h;
182
183 /* y component */
184 ty = iy = ay;
185 ty += 2.*iy + h*ty;
186 ty += 2.*iy + h*ty;
187 ty += iy + h*ty;
188 ty *= h/6.;
189
190 vy += ty;
191 py += vy * h;
192
193 /* rotation. */
194 obj->dir += obj->dir_vel*h;
195 }
196 vec2_cset( &obj->vel, vx, vy );
197 vec2_cset( &obj->pos, px, py );
198
199 /* Validity check. */
200 if (obj->dir >= 2.*M_PI)
201 obj->dir -= 2.*M_PI;
202 else if (obj->dir < 0.)
203 obj->dir += 2.*M_PI;
204}
205
209double solid_maxspeed( const Solid *s, double speed, double thrust )
210{
211 return speed + thrust / (s->mass * 3.);
212}
213
223void solid_init( Solid* dest, double mass, double dir,
224 const vec2* pos, const vec2* vel, int update )
225{
226 memset(dest, 0, sizeof(Solid));
227
228 dest->mass = mass;
229
230 /* Set direction velocity. */
231 dest->dir_vel = 0.;
232
233 /* Set force. */
234 dest->thrust = 0.;
235
236 /* Set direction. */
237 dest->dir = dir;
238 if ((dest->dir > 2.*M_PI) || (dest->dir < 0.))
239 dest->dir = fmod(dest->dir, 2.*M_PI);
240
241 /* Set velocity. */
242 if (vel == NULL)
243 vectnull( &dest->vel );
244 else
245 dest->vel = *vel;
246
247 /* Set position. */
248 if (pos == NULL)
249 vectnull( &dest->pos );
250 else
251 dest->pos = *pos;
252
253 /* Misc. */
254 dest->speed_max = -1.; /* Negative is invalid. */
255
256 /* Handle update. */
257 switch (update) {
258 case SOLID_UPDATE_RK4:
259 dest->update = solid_update_rk4;
260 break;
261
262 case SOLID_UPDATE_EULER:
263 dest->update = solid_update_euler;
264 break;
265
266 default:
267 WARN(_("Solid initialization did not specify correct update function!"));
268 dest->update = solid_update_rk4;
269 break;
270 }
271}
272
282Solid* solid_create( double mass, double dir,
283 const vec2* pos, const vec2* vel, int update )
284{
285 Solid* dyn = malloc(sizeof(Solid));
286 if (dyn==NULL)
287 ERR(_("Out of Memory"));
288 solid_init( dyn, mass, dir, pos, vel, update );
289 return dyn;
290}
291
297void solid_free( Solid* src )
298{
299 free(src);
300}
Header file with generic functions and naev-specifics.
#define FABS(x)
Definition: naev.h:37
static const double a[]
Definition: rng.c:247
static const double d[]
Definition: rng.c:273
Represents a solid in the game.
Definition: physics.h:17
double dir_vel
Definition: physics.h:20
double speed_max
Definition: physics.h:24
void(* update)(struct Solid_ *, double)
Definition: physics.h:25
vec2 vel
Definition: physics.h:21
double thrust
Definition: physics.h:23
double dir
Definition: physics.h:19
double mass
Definition: physics.h:18
vec2 pos
Definition: physics.h:22
Represents a 2d vector.
Definition: vec2.h:32
double y
Definition: vec2.h:34
double x
Definition: vec2.h:33