naev 0.10.4
background.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
13#include "background.h"
14
15#include "array.h"
16#include "camera.h"
17#include "conf.h"
18#include "log.h"
19#include "gui.h"
20#include "ndata.h"
21#include "nebula.h"
22#include "nlua.h"
23#include "nlua_audio.h"
24#include "nlua_bkg.h"
25#include "nlua_colour.h"
26#include "nlua_tex.h"
27#include "nlua_camera.h"
28#include "nlua_gfx.h"
29#include "nluadef.h"
30#include "nstring.h"
31#include "nxml.h"
32#include "opengl.h"
33#include "pause.h"
34#include "player.h"
35#include "rng.h"
36
40typedef struct background_image_s {
41 unsigned int id;
43 double x;
44 double y;
45 double move;
46 double scale;
47 double angle;
48 glColour col;
53static unsigned int bkg_idgen = 0;
58static nlua_env bkg_cur_env = LUA_NOREF;
59static nlua_env bkg_def_env = LUA_NOREF;
60static int bkg_L_renderbg = LUA_NOREF;
61static int bkg_L_rendermg = LUA_NOREF;
62static int bkg_L_renderfg = LUA_NOREF;
63static int bkg_L_renderov = LUA_NOREF;
65/*
66 * Background stars.
67 */
68#define STAR_BUF 250
69static gl_vbo *star_vertexVBO = NULL;
70static unsigned int nstars = 0;
71static GLfloat star_x = 0.;
72static GLfloat star_y = 0.;
74/*
75 * Prototypes.
76 */
77static void background_renderImages( background_image_t *bkg_arr );
78static nlua_env background_create( const char *path );
79static void background_clearCurrent (void);
81/* Sorting. */
82static int bkg_compare( const void *p1, const void *p2 );
83static void bkg_sort( background_image_t *arr );
84
91{
92 GLfloat w, h, hw, hh;
93 double size;
94 GLfloat *star_vertex;
95
96 /* Calculate size. */
97 size = SCREEN_W*SCREEN_H+STAR_BUF*STAR_BUF;
98 size /= pow2(conf.zoom_far);
99
100 /* Calculate star buffer. */
101 w = (SCREEN_W + 2.*STAR_BUF);
102 w += conf.zoom_stars * (w / conf.zoom_far - 1.);
103 h = (SCREEN_H + 2.*STAR_BUF);
104 h += conf.zoom_stars * (h / conf.zoom_far - 1.);
105 hw = w / 2.;
106 hh = h / 2.;
107
108 /* Calculate stars. */
109 size *= n;
110 nstars = (unsigned int)(size/(800.*600.));
111
112 /* Create data. */
113 star_vertex = malloc( nstars * sizeof(GLfloat) * 6 );
114
115 for (unsigned int i=0; i < nstars; i++) {
116 /* Set the position. */
117 star_vertex[6*i+0] = RNGF()*w - hw;
118 star_vertex[6*i+1] = RNGF()*h - hh;
119 star_vertex[6*i+3] = star_vertex[6*i+0];
120 star_vertex[6*i+4] = star_vertex[6*i+1];
121 /* Set the colour. */
122 star_vertex[6*i+2] = RNGF()*0.6 + 0.2;
123 star_vertex[6*i+5] = star_vertex[6*i+2];
124 }
125
126 /* Recreate VBO. */
129 nstars * sizeof(GLfloat) * 6, star_vertex );
130
131 free(star_vertex);
132}
133
137void background_moveDust( double x, double y )
138{
139 star_x += (GLfloat) x;
140 star_y += (GLfloat) y;
141}
142
148void background_renderDust( const double dt )
149{
150 (void) dt;
151 GLfloat x, y, h, w, m;
152 double z;
153 mat4 projection;
154 int points = 1;
155
156 /* Do some scaling for now. */
157 z = cam_getZoom();
158 z = 1. * (1. - conf.zoom_stars) + z * conf.zoom_stars;
159 m = 1.;
160 projection = gl_view_matrix;
161 mat4_translate( &projection, SCREEN_W/2., SCREEN_H/2., 0 );
162 mat4_scale( &projection, z, z, 1 );
163
164 /* Decide on shade mode. */
165 if ((player.p != NULL) && !player_isFlag(PLAYER_DESTROYED) &&
166 !player_isFlag(PLAYER_CREATING)) {
167 double dx, dy, vmod;
168
169 /* Get camera movement. */
170 cam_getVel( &dx, &dy );
171 vmod = hypot( dx, dy );
172
173 if (pilot_isFlag(player.p,PILOT_HYPERSPACE)) { /* hyperspace fancy effects */
174 /* lines get longer the closer we are to finishing the jump */
175 m = MAX( 0, HYPERSPACE_STARS_BLUR-player.p->ptimer );
176 m /= HYPERSPACE_STARS_BLUR;
177 m *= HYPERSPACE_STARS_LENGTH;
178 if (m > 1.) {
179 double angle = atan2( dy, dx );
180 x = m * cos( angle );
181 y = m * sin( angle );
182 points = 0;
183 }
184 }
185 else if (dt_mod * vmod > 500. ) {
186 /* Very short lines tend to flicker horribly. A stock Llama at 2x
187 * speed just so happens to make very short lines. A 5px minimum
188 * is long enough to (mostly) alleviate the flickering. */
189 /* TODO don't use GL_LINES. */
190 double angle = atan2( dy, dx );
191 m = MAX( 5., dt_mod * vmod/25. - 20 );
192 x = m * cos( angle );
193 y = m * sin( angle );
194 points = 0;
195 }
196 }
197
198 /* Calculate some dimensions. */
199 w = (SCREEN_W + 2.*STAR_BUF);
200 w += conf.zoom_stars * (w / conf.zoom_far - 1.);
201 h = (SCREEN_H + 2.*STAR_BUF);
202 h += conf.zoom_stars * (h / conf.zoom_far - 1.);
203
204 /* Common shader stuff. */
205 glUseProgram(shaders.stars.program);
206 gl_uniformMat4(shaders.stars.projection, &projection);
207 glUniform2f(shaders.stars.star_xy, star_x, star_y);
208 glUniform3f(shaders.stars.dims, w, h, 1. / gl_screen.scale);
209 glUniform1i(shaders.stars.use_lines, !points);
210 glUniform1f(shaders.stars.dim, CLAMP(0.5, 1., 1.-(m-1.)/25.) );
211
212 /* Vertices. */
213 glEnableVertexAttribArray( shaders.stars.vertex );
214 glEnableVertexAttribArray( shaders.stars.brightness );
215
216 /* Set up the vertices. */
217 if (points) {
218 gl_vboActivateAttribOffset( star_vertexVBO, shaders.stars.vertex, 0,
219 2, GL_FLOAT, 6 * sizeof(GLfloat) );
220 gl_vboActivateAttribOffset( star_vertexVBO, shaders.stars.brightness, 2 * sizeof(GLfloat),
221 1, GL_FLOAT, 6 * sizeof(GLfloat) );
222 glUniform2f(shaders.stars.xy, 0., 0.);
223 glDrawArrays( GL_POINTS, 0, nstars/2 );
224 }
225 else {
226 gl_vboActivateAttribOffset( star_vertexVBO, shaders.stars.vertex, 0,
227 2, GL_FLOAT, 3 * sizeof(GLfloat) );
228 gl_vboActivateAttribOffset( star_vertexVBO, shaders.stars.brightness, 2 * sizeof(GLfloat),
229 1, GL_FLOAT, 3 * sizeof(GLfloat) );
230 glUniform2f(shaders.stars.xy, x, y);
231 glDrawArrays( GL_LINES, 0, nstars );
232 }
233
234 /* Disable vertex array. */
235 glDisableVertexAttribArray( shaders.stars.vertex );
236 glDisableVertexAttribArray( shaders.stars.brightness );
237
238 glUseProgram(0);
239
240 /* Check for errors. */
241 gl_checkErr();
242}
243
249void background_render( double dt )
250{
251 if (bkg_L_renderbg != LUA_NOREF) {
252 lua_rawgeti( naevL, LUA_REGISTRYINDEX, bkg_L_renderbg );
253 lua_pushnumber( naevL, dt ); /* Note that this is real_dt. */
254 if (nlua_pcall( bkg_cur_env, 1, 0 )) {
255 WARN( _("Background script 'renderbg' error:\n%s"), lua_tostring(naevL,-1));
256 lua_pop( naevL, 1 );
257 }
258 }
259
261
262 if (bkg_L_rendermg != LUA_NOREF) {
263 lua_rawgeti( naevL, LUA_REGISTRYINDEX, bkg_L_rendermg );
264 lua_pushnumber( naevL, dt ); /* Note that this is real_dt. */
265 if (nlua_pcall( bkg_cur_env, 1, 0 )) {
266 WARN( _("Background script 'rendermg' error:\n%s"), lua_tostring(naevL,-1));
267 lua_pop( naevL, 1 );
268 }
269 }
270
273
274 if (bkg_L_renderfg != LUA_NOREF) {
275 lua_rawgeti( naevL, LUA_REGISTRYINDEX, bkg_L_renderfg );
276 lua_pushnumber( naevL, dt ); /* Note that this is real_dt. */
277 if (nlua_pcall( bkg_cur_env, 1, 0 )) {
278 WARN( _("Background script 'renderfg' error:\n%s"), lua_tostring(naevL,-1));
279 lua_pop( naevL, 1 );
280 }
281 }
282}
283
288{
289 if (bkg_L_renderov != LUA_NOREF) {
290 lua_rawgeti( naevL, LUA_REGISTRYINDEX, bkg_L_renderov );
291 lua_pushnumber( naevL, dt ); /* Note that this is real_dt. */
292 if (nlua_pcall( bkg_cur_env, 1, 0 )) {
293 WARN( _("Background script 'renderov' error:\n%s"), lua_tostring(naevL,-1));
294 lua_pop( naevL, 1 );
295 }
296 }
297}
298
302static int bkg_compare( const void *p1, const void *p2 )
303{
304 background_image_t *bkg1, *bkg2;
305
306 bkg1 = (background_image_t*) p1;
307 bkg2 = (background_image_t*) p2;
308
309 if (bkg1->move < bkg2->move)
310 return -1;
311 else if (bkg1->move > bkg2->move)
312 return +1;
313 return 0;
314}
315
319static void bkg_sort( background_image_t *arr )
320{
321 qsort( arr, array_size(arr), sizeof(background_image_t), bkg_compare );
322}
323
327unsigned int background_addImage( glTexture *image, double x, double y,
328 double move, double scale, double angle, const glColour *col, int foreground )
329{
330 background_image_t *bkg, **arr;
331
332 if (foreground)
333 arr = &bkg_image_arr_ft;
334 else
335 arr = &bkg_image_arr_bk;
336
337 /* See if must create. */
338 if (*arr == NULL)
340
341 /* Create image. */
342 bkg = &array_grow( arr );
343 bkg->id = ++bkg_idgen;
344 bkg->image = gl_dupTexture(image);
345 bkg->x = x;
346 bkg->y = y;
347 bkg->move = move;
348 bkg->scale = scale;
349 bkg->angle = angle;
350 bkg->col = (col!=NULL) ? *col : cWhite;
351
352 /* Sort if necessary. */
353 bkg_sort( *arr );
354
355 return bkg_idgen;
356}
357
362{
363 /* Skip rendering altogether if disabled. */
364 if (conf.bg_brightness <= 0.)
365 return;
366
367 /* Render images in order. */
368 for (int i=0; i<array_size(bkg_arr); i++) {
369 double cx,cy, x,y, gx,gy, z, m;
370 glColour col;
371 background_image_t *bkg = &bkg_arr[i];
372
373 cam_getPos( &cx, &cy );
374 gui_getOffset( &gx, &gy );
375 m = bkg->move;
376 z = bkg->scale;
377 x = (bkg->x - cx) * m - z*bkg->image->sw/2. + gx + SCREEN_W/2.;
378 y = (bkg->y - cy) * m - z*bkg->image->sh/2. + gy + SCREEN_H/2.;
379
380 col.r = bkg->col.r * conf.bg_brightness;
381 col.g = bkg->col.g * conf.bg_brightness;
382 col.b = bkg->col.b * conf.bg_brightness;
383 col.a = bkg->col.a;
384
385 gl_renderTexture( bkg->image, x, y, z*bkg->image->sw, z*bkg->image->sh, 0., 0., bkg->image->srw, bkg->image->srh, &col, bkg->angle );
386 }
387}
388
392static nlua_env background_create( const char *name )
393{
394 size_t bufsize;
395 char path[PATH_MAX];
396 char *buf;
397 nlua_env env;
398
399 /* Create file name. */
400 snprintf( path, sizeof(path), BACKGROUND_PATH"%s.lua", name );
401
402 /* Create the Lua env. */
403 env = nlua_newEnv();
405 nlua_loadTex(env);
406 nlua_loadCol(env);
408 nlua_loadCamera(env);
409 nlua_loadGFX(env);
410
411 /* Open file. */
412 buf = ndata_read( path, &bufsize );
413 if (buf == NULL) {
414 WARN( _("Background script '%s' not found."), path);
415 nlua_freeEnv(env);
416 return LUA_NOREF;
417 }
418
419 /* Load file. */
420 if (nlua_dobufenv(env, buf, bufsize, path) != 0) {
421 WARN( _("Error loading background file: %s\n"
422 "%s\n"
423 "Most likely Lua file has improper syntax, please check"),
424 path, lua_tostring(naevL,-1));
425 free(buf);
426 nlua_freeEnv(env);
427 return LUA_NOREF;
428 }
429 free(buf);
430
431 return env;
432}
433
438{
439 /* Load Lua. */
440 bkg_def_env = background_create( "default" );
441 return 0;
442}
443
447int background_load( const char *name )
448{
449 int ret;
450 nlua_env env;
451
452 /* Free if exists. */
454
455 /* Load default. */
456 if (name == NULL)
458 /* Load new script. */
459 else
461
462 /* Comfort. */
463 env = bkg_cur_env;
464 if (env == LUA_NOREF)
465 return -1;
466
467 /* Run Lua. */
468 nlua_getenv(naevL, env,"background");
469 ret = nlua_pcall(env, 0, 0);
470 if (ret != 0) { /* error has occurred */
471 const char *err = (lua_isstring(naevL,-1)) ? lua_tostring(naevL,-1) : NULL;
472 WARN( _("Background -> 'background' : %s"),
473 (err) ? err : _("unknown error"));
474 lua_pop(naevL, 1);
475 }
476
477 /* See if there are render functions. */
478 bkg_L_renderbg = nlua_refenv( env, "renderbg" );
479 bkg_L_rendermg = nlua_refenv( env, "rendermg" );
480 bkg_L_renderfg = nlua_refenv( env, "renderfg" );
481 bkg_L_renderov = nlua_refenv( env, "renderov" );
482
483 return ret;
484}
485
489static void background_clearCurrent (void)
490{
491 if (bkg_cur_env != bkg_def_env) {
492 nlua_freeEnv( bkg_cur_env );
493 }
494 bkg_cur_env = LUA_NOREF;
495
496 luaL_unref( naevL, LUA_REGISTRYINDEX, bkg_L_renderbg );
497 luaL_unref( naevL, LUA_REGISTRYINDEX, bkg_L_rendermg );
498 luaL_unref( naevL, LUA_REGISTRYINDEX, bkg_L_renderfg );
499 luaL_unref( naevL, LUA_REGISTRYINDEX, bkg_L_renderov );
500 bkg_L_renderbg = LUA_NOREF;
501 bkg_L_rendermg = LUA_NOREF;
502 bkg_L_renderfg = LUA_NOREF;
503 bkg_L_renderov = LUA_NOREF;
504}
505
510{
511 /* Destroy current background script. */
513
514 /* Clear the backgrounds. */
517}
518
525{
526 for (int i=0; i<array_size(*arr); i++) {
527 background_image_t *bkg = &((*arr)[i]);
528 gl_freeTexture( bkg->image );
529 }
530
531 /* Erase it all. */
532 array_erase( arr, array_begin(*arr), array_end(*arr) );
533}
534
539{
540 /* Free the Lua. */
542 nlua_freeEnv( bkg_def_env );
543 bkg_def_env = LUA_NOREF;
544
545 /* Free the images. */
547 bkg_image_arr_ft = NULL;
549 bkg_image_arr_bk = NULL;
550
551 /* Free the Lua. */
552 nlua_freeEnv( bkg_cur_env );
553 bkg_cur_env = LUA_NOREF;
554
556 star_vertexVBO = NULL;
557
558 nstars = 0;
559}
560
565{
567 for (int i=0; i<array_size(bkg_image_arr_bk); i++)
569 return imgs;
570}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition: array.h:158
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
Definition: array.h:202
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
Definition: array.h:102
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition: array.h:140
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition: array.h:168
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
Definition: array.h:119
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition: array.h:129
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
Definition: array.h:194
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition: array.h:93
static background_image_t * bkg_image_arr_bk
Definition: background.c:50
static GLfloat star_y
Definition: background.c:72
unsigned int background_addImage(glTexture *image, double x, double y, double move, double scale, double angle, const glColour *col, int foreground)
Adds a new background image.
Definition: background.c:327
glTexture ** background_getTextures(void)
returns the background images, and number of these
Definition: background.c:564
void background_clear(void)
Cleans up the background stuff.
Definition: background.c:509
int background_init(void)
Initializes the background system.
Definition: background.c:437
static unsigned int bkg_idgen
Definition: background.c:53
static int bkg_L_renderov
Definition: background.c:63
static background_image_t * bkg_image_arr_ft
Definition: background.c:51
#define STAR_BUF
Definition: background.c:68
void background_initDust(int n)
Initializes background stars.
Definition: background.c:90
static int bkg_L_renderbg
Definition: background.c:60
void background_renderOverlay(double dt)
Renders the background overlay.
Definition: background.c:287
static int bkg_L_rendermg
Definition: background.c:61
static GLfloat star_x
Definition: background.c:71
static nlua_env bkg_def_env
Definition: background.c:59
void background_moveDust(double x, double y)
Displaces the stars, useful with camera.
Definition: background.c:137
static int bkg_L_renderfg
Definition: background.c:62
static unsigned int nstars
Definition: background.c:70
void background_free(void)
Cleans up and frees memory after the backgrounds.
Definition: background.c:538
static void background_clearCurrent(void)
Destroys the current running background script.
Definition: background.c:489
static int bkg_compare(const void *p1, const void *p2)
Compares two different backgrounds and sorts them.
Definition: background.c:302
static void background_renderImages(background_image_t *bkg_arr)
Renders the background images.
Definition: background.c:361
static gl_vbo * star_vertexVBO
Definition: background.c:69
void background_renderDust(const double dt)
Renders the starry background.
Definition: background.c:148
static void background_clearImgArr(background_image_t **arr)
Clears a background image array.
Definition: background.c:524
static void bkg_sort(background_image_t *arr)
Sorts the backgrounds by movement.
Definition: background.c:319
static nlua_env background_create(const char *path)
Creates a background Lua state from a script.
Definition: background.c:392
void background_render(double dt)
Render the background.
Definition: background.c:249
static nlua_env bkg_cur_env
Backgrounds.
Definition: background.c:58
int background_load(const char *name)
Loads a background script by name.
Definition: background.c:447
void cam_getVel(double *vx, double *vy)
Gets the camera velocity.
Definition: camera.c:136
void cam_getPos(double *x, double *y)
Gets the camera position.
Definition: camera.c:118
double cam_getZoom(void)
Gets the camera zoom.
Definition: camera.c:97
void gui_getOffset(double *x, double *y)
Gets the GUI offset.
Definition: gui.c:2021
void mat4_translate(mat4 *m, double x, double y, double z)
Translates a homogenous transformation matrix.
Definition: mat4.c:99
void mat4_scale(mat4 *m, double x, double y, double z)
Scales a homogeneous transformation matrix.
Definition: mat4.c:82
Header file with generic functions and naev-specifics.
#define CLAMP(a, b, x)
Definition: naev.h:41
#define pow2(x)
Definition: naev.h:46
#define MAX(x, y)
Definition: naev.h:39
#define PATH_MAX
Definition: naev.h:50
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
Definition: ndata.c:154
static char buf[NEWS_MAX_LENGTH]
Definition: news.c:45
int nlua_refenv(nlua_env env, const char *name)
Gets the reference of a global in a lua environment.
Definition: nlua.c:856
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition: nlua.c:760
int nlua_loadBackground(nlua_env env)
Loads the graphics library.
Definition: nlua_bkg.c:38
int nlua_loadCamera(nlua_env env)
Loads the camera library.
Definition: nlua_camera.c:47
int nlua_loadCol(nlua_env env)
Loads the colour library.
Definition: nlua_colour.c:52
int nlua_loadGFX(nlua_env env)
Loads the graphics library.
Definition: nlua_gfx.c:97
int nlua_loadTex(nlua_env env)
Loads the texture library.
Definition: nlua_tex.c:62
glInfo gl_screen
Definition: opengl.c:51
void gl_renderTexture(const glTexture *texture, double x, double y, double w, double h, double tx, double ty, double tw, double th, const glColour *c, double angle)
Texture blitting backend.
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
Definition: opengl_tex.c:809
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition: opengl_tex.c:755
void gl_vboDestroy(gl_vbo *vbo)
Destroys a VBO.
Definition: opengl_vbo.c:248
void gl_vboActivateAttribOffset(gl_vbo *vbo, GLuint index, GLuint offset, GLint size, GLenum type, GLsizei stride)
Activates a VBO's offset.
Definition: opengl_vbo.c:228
gl_vbo * gl_vboCreateStatic(GLsizei size, const void *data)
Creates a stream vbo.
Definition: opengl_vbo.c:181
double dt_mod
Definition: pause.c:23
Player_t player
Definition: player.c:73
double ptimer
Definition: pilot.h:356
double zoom_stars
Definition: conf.h:138
double zoom_far
Definition: conf.h:135
double bg_brightness
Definition: conf.h:99
Pilot * p
Definition: player.h:101
Represents a background image like say a Nebula.
Definition: background.c:40
glTexture * image
Definition: background.c:42
unsigned int id
Definition: background.c:41
double scale
Definition: opengl.h:48
Abstraction for rendering sprite sheets.
Definition: opengl_tex.h:34
double sw
Definition: opengl_tex.h:44
double sh
Definition: opengl_tex.h:45
double srh
Definition: opengl_tex.h:47
double srw
Definition: opengl_tex.h:46
Definition: mat4.h:10