1 /*
2  * Copyright (C) 2003-2010 Neverball authors
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14 
15 #include "game_common.h"
16 #include "vec3.h"
17 #include "config.h"
18 #include "solid_vary.h"
19 #include "hmd.h"
20 #include "common.h"
21 
22 /*---------------------------------------------------------------------------*/
23 
status_to_str(int s)24 const char *status_to_str(int s)
25 {
26     switch (s)
27     {
28     case GAME_NONE: return _("Aborted");
29     case GAME_TIME: return _("Time-out");
30     case GAME_GOAL: return _("Success");
31     case GAME_FALL: return _("Fall-out");
32     default:        return _("Unknown");
33     }
34 }
35 
36 /*---------------------------------------------------------------------------*/
37 
cam_to_str(int c)38 const char *cam_to_str(int c)
39 {
40     static char str[64];
41 
42     int s = cam_speed(c);
43 
44     if (s <    0) return _("Manual Camera");
45     if (s <= 100) return _("Lazy Camera");
46     if (s <= 500) return _("Chase Camera");
47 
48     sprintf(str, _("Camera %d"), c + 1);
49 
50     return str;
51 }
52 
cam_speed(int c)53 int cam_speed(int c)
54 {
55     static const int *cfgs[] = {
56         &CONFIG_CAMERA_1_SPEED,
57         &CONFIG_CAMERA_2_SPEED,
58         &CONFIG_CAMERA_3_SPEED
59     };
60 
61     if (c >= 0 && c < ARRAYSIZE(cfgs))
62         return config_get_d(*cfgs[c]);
63 
64     return 250;
65 }
66 
67 /*---------------------------------------------------------------------------*/
68 
69 const float GRAVITY_UP[] = { 0.0f, +9.8f, 0.0f };
70 const float GRAVITY_DN[] = { 0.0f, -9.8f, 0.0f };
71 
game_tilt_init(struct game_tilt * tilt)72 void game_tilt_init(struct game_tilt *tilt)
73 {
74     tilt->x[0] = 1.0f;
75     tilt->x[1] = 0.0f;
76     tilt->x[2] = 0.0f;
77 
78     tilt->rx = 0.0f;
79 
80     tilt->z[0] = 0.0f;
81     tilt->z[1] = 0.0f;
82     tilt->z[2] = 1.0f;
83 
84     tilt->rz = 0.0f;
85 }
86 
87 /*
88  * Compute appropriate tilt axes from the view basis.
89  */
game_tilt_axes(struct game_tilt * tilt,float view_e[3][3])90 void game_tilt_axes(struct game_tilt *tilt, float view_e[3][3])
91 {
92     v_cpy(tilt->x, view_e[0]);
93     v_cpy(tilt->z, view_e[2]);
94 }
95 
game_tilt_grav(float h[3],const float g[3],const struct game_tilt * tilt)96 void game_tilt_grav(float h[3], const float g[3], const struct game_tilt *tilt)
97 {
98     float X[16];
99     float Z[16];
100     float M[16];
101 
102     /* Compute the gravity vector from the given world rotations. */
103 
104     m_rot (Z, tilt->z, V_RAD(tilt->rz));
105     m_rot (X, tilt->x, V_RAD(tilt->rx));
106     m_mult(M, Z, X);
107     m_vxfm(h, M, g);
108 }
109 
110 /*---------------------------------------------------------------------------*/
111 
game_view_init(struct game_view * view)112 void game_view_init(struct game_view *view)
113 {
114     /* In VR, ensure the default view is level. */
115 
116     if (hmd_stat())
117     {
118         view->dp = config_get_d(CONFIG_VIEW_DP) / 100.0f;
119         view->dc = config_get_d(CONFIG_VIEW_DP) / 100.0f;
120         view->dz = config_get_d(CONFIG_VIEW_DZ) / 100.0f;
121     }
122     else
123     {
124         view->dp = config_get_d(CONFIG_VIEW_DP) / 100.0f;
125         view->dc = config_get_d(CONFIG_VIEW_DC) / 100.0f;
126         view->dz = config_get_d(CONFIG_VIEW_DZ) / 100.0f;
127     }
128 
129     view->a = 0.0f;
130 
131     view->c[0] = 0.0f;
132     view->c[1] = view->dc;
133     view->c[2] = 0.0f;
134 
135     view->p[0] =     0.0f;
136     view->p[1] = view->dp;
137     view->p[2] = view->dz;
138 
139     view->e[0][0] = 1.0f;
140     view->e[0][1] = 0.0f;
141     view->e[0][2] = 0.0f;
142     view->e[1][0] = 0.0f;
143     view->e[1][1] = 1.0f;
144     view->e[1][2] = 0.0f;
145     view->e[2][0] = 0.0f;
146     view->e[2][1] = 0.0f;
147     view->e[2][2] = 1.0f;
148 }
149 
game_view_fly(struct game_view * view,const struct s_vary * vary,float k)150 void game_view_fly(struct game_view *view, const struct s_vary *vary, float k)
151 {
152     /* float  x[3] = { 1.f, 0.f, 0.f }; */
153     float  y[3] = { 0.f, 1.f, 0.f };
154     float  z[3] = { 0.f, 0.f, 1.f };
155     float c0[3] = { 0.f, 0.f, 0.f };
156     float p0[3] = { 0.f, 0.f, 0.f };
157     float c1[3] = { 0.f, 0.f, 0.f };
158     float p1[3] = { 0.f, 0.f, 0.f };
159     float  v[3];
160 
161     game_view_init(view);
162 
163     /* k = 0.0 view is at the ball. */
164 
165     if (vary->uc > 0)
166     {
167         v_cpy(c0, vary->uv[0].p);
168         v_cpy(p0, vary->uv[0].p);
169     }
170 
171     v_mad(p0, p0, y, view->dp);
172     v_mad(p0, p0, z, view->dz);
173     v_mad(c0, c0, y, view->dc);
174 
175     /* k = +1.0 view is s_view 0 */
176 
177     if (k >= 0 && vary->base->wc > 0)
178     {
179         v_cpy(p1, vary->base->wv[0].p);
180         v_cpy(c1, vary->base->wv[0].q);
181     }
182 
183     /* k = -1.0 view is s_view 1 */
184 
185     if (k <= 0 && vary->base->wc > 1)
186     {
187         v_cpy(p1, vary->base->wv[1].p);
188         v_cpy(c1, vary->base->wv[1].q);
189     }
190 
191     /* Interpolate the views. */
192 
193     v_sub(v, p1, p0);
194     v_mad(view->p, p0, v, k * k);
195 
196     v_sub(v, c1, c0);
197     v_mad(view->c, c0, v, k * k);
198 
199     /* Orthonormalize the view basis. */
200 
201     v_sub(view->e[2], view->p, view->c);
202     v_crs(view->e[0], view->e[1], view->e[2]);
203     v_crs(view->e[2], view->e[0], view->e[1]);
204     v_nrm(view->e[0], view->e[0]);
205     v_nrm(view->e[2], view->e[2]);
206 }
207 
208 /*---------------------------------------------------------------------------*/
209 
lockstep_clr(struct lockstep * ls)210 void lockstep_clr(struct lockstep *ls)
211 {
212     ls->at = 0;
213     ls->ts = 1.0f;
214 }
215 
lockstep_run(struct lockstep * ls,float dt)216 void lockstep_run(struct lockstep *ls, float dt)
217 {
218     ls->at += dt * ls->ts;
219 
220     while (ls->at >= ls->dt)
221     {
222         ls->step(ls->dt);
223         ls->at -= ls->dt;
224     }
225 }
226 
lockstep_scl(struct lockstep * ls,float ts)227 void lockstep_scl(struct lockstep *ls, float ts)
228 {
229     ls->ts = ts;
230 }
231 
232 /*---------------------------------------------------------------------------*/
233 
234 /* Poor man's cache. */
235 
236 struct s_base  game_base;
237 static char   *base_path;
238 
game_base_load(const char * path)239 int game_base_load(const char *path)
240 {
241     if (base_path)
242     {
243         if (strcmp(base_path, path) == 0)
244             return 1;
245 
246         sol_free_base(&game_base);
247 
248         free(base_path);
249         base_path = NULL;
250     }
251 
252     if (sol_load_base(&game_base, path))
253     {
254         base_path = strdup(path);
255         return 1;
256     }
257 
258     return 0;
259 }
260 
261 
game_base_free(const char * next)262 void game_base_free(const char *next)
263 {
264     if (base_path)
265     {
266         if (next && strcmp(base_path, next) == 0)
267             return;
268 
269         sol_free_base(&game_base);
270 
271         free(base_path);
272         base_path = NULL;
273     }
274 }
275 
276 /*---------------------------------------------------------------------------*/
277 
278 float SPEED_FACTORS[SPEED_MAX] = {
279     0.0f,
280     1.0f / 8,
281     1.0f / 4,
282     1.0f / 2,
283     1.0f,
284     1.0f * 2,
285     1.0f * 4,
286     1.0f * 8
287 };
288 
289 /*---------------------------------------------------------------------------*/
290