25#include "nlua_camera.h"
30#include "opengl_tex.h"
34#include "threadpool.h"
36#define XML_SHIP "ship"
38#define SHIP_ENGINE "_engine"
39#define SHIP_TARGET "_target"
40#define SHIP_COMM "_comm"
43#define VIEW_HEIGHT 300
45#define BUTTON_WIDTH 80
46#define BUTTON_HEIGHT 30
48#define STATS_DESC_MAX 512
53typedef struct ShipThreadData_ {
62static double max_size = 512.;
63static double ship_fbos = 0.;
64static GLuint ship_fbo[SHIP_FBO] = { GL_INVALID_ENUM };
65static GLuint ship_tex[SHIP_FBO] = { GL_INVALID_ENUM };
66static GLuint ship_texd[SHIP_FBO] = { GL_INVALID_ENUM };
67static const double ship_aa_scale_base = 2.;
68static double ship_aa_scale = -1.;
74static int ship_parse(
Ship *temp,
const char *filename,
int firstpass );
78 double fw,
double fh,
double engine_glow,
79 double t,
const glColour *
c,
81 int blit,
unsigned int flags );
86static int ship_cmp(
const void *p1,
const void *p2 )
103 WARN( _(
"Ship %s does not exist" ), name );
115 const Ship s = { .name = (
char *)name };
126 if ( strcasecmp( name,
ship_stack[i].name ) == 0 )
147 s1 = *(
const Ship **)arg1;
148 s2 = *(
const Ship **)arg2;
183 return strcmp( s1->
name, s2->
name );
219 case SHIP_CLASS_NULL:
222 case SHIP_CLASS_YACHT:
223 return N_(
"Yacht" );
224 case SHIP_CLASS_COURIER:
225 return N_(
"Courier" );
226 case SHIP_CLASS_FREIGHTER:
227 return N_(
"Freighter" );
228 case SHIP_CLASS_ARMOURED_TRANSPORT:
229 return N_(
"Armoured Transport" );
230 case SHIP_CLASS_BULK_FREIGHTER:
231 return N_(
"Bulk Freighter" );
233 case SHIP_CLASS_SCOUT:
234 return N_(
"Scout" );
235 case SHIP_CLASS_INTERCEPTOR:
236 return N_(
"Interceptor" );
237 case SHIP_CLASS_FIGHTER:
238 return N_(
"Fighter" );
239 case SHIP_CLASS_BOMBER:
240 return N_(
"Bomber" );
241 case SHIP_CLASS_CORVETTE:
242 return N_(
"Corvette" );
243 case SHIP_CLASS_DESTROYER:
244 return N_(
"Destroyer" );
245 case SHIP_CLASS_CRUISER:
246 return N_(
"Cruiser" );
247 case SHIP_CLASS_BATTLESHIP:
248 return N_(
"Battleship" );
249 case SHIP_CLASS_CARRIER:
250 return N_(
"Carrier" );
253 return N_(
"Unknown" );
257#define STRTOSHIP( x, y ) \
258 if ( strcmp( str, x ) == 0 ) \
268 return SHIP_CLASS_NULL;
270 STRTOSHIP(
"Yacht", SHIP_CLASS_YACHT );
271 STRTOSHIP(
"Courier", SHIP_CLASS_COURIER );
272 STRTOSHIP(
"Freighter", SHIP_CLASS_FREIGHTER );
273 STRTOSHIP(
"Armoured Transport", SHIP_CLASS_ARMOURED_TRANSPORT );
274 STRTOSHIP(
"Bulk Freighter", SHIP_CLASS_BULK_FREIGHTER );
277 STRTOSHIP(
"Scout", SHIP_CLASS_SCOUT );
278 STRTOSHIP(
"Interceptor", SHIP_CLASS_INTERCEPTOR );
279 STRTOSHIP(
"Fighter", SHIP_CLASS_FIGHTER );
280 STRTOSHIP(
"Bomber", SHIP_CLASS_BOMBER );
281 STRTOSHIP(
"Corvette", SHIP_CLASS_CORVETTE );
282 STRTOSHIP(
"Destroyer", SHIP_CLASS_DESTROYER );
283 STRTOSHIP(
"Cruiser", SHIP_CLASS_CRUISER );
284 STRTOSHIP(
"Battleship", SHIP_CLASS_BATTLESHIP );
285 STRTOSHIP(
"Carrier", SHIP_CLASS_CARRIER );
288 return SHIP_CLASS_NULL;
327void ship_renderGfxStore( GLuint fbo,
const Ship *s,
int size,
double dir,
328 double updown,
double glow )
330 glBindFramebuffer( GL_FRAMEBUFFER, fbo );
331 glClear( GL_COLOR_BUFFER_BIT );
337 glUseProgram( shaders.shop_bg.program );
342 if ( s->
gfx_3d != NULL ) {
345 double t = SDL_GetTicks() / 1000.;
351 mat4_rotate( &H, -M_PI_4 * 0.25 + updown, 1.0, 0.0, 0.0 );
355 t, &cWhite, &L, &H, 0, OPENGL_TEX_VFLIP );
359 double scale, w, h, tx, ty;
363 glcomm->
flags &= ~OPENGL_TEX_VFLIP;
365 scale =
MIN( size / glcomm->
w, size / glcomm->
h );
366 w = scale * glcomm->
w;
367 h = scale * glcomm->
h;
369 tx = glcomm->
sw * (double)( sx ) / glcomm->
w;
370 ty = glcomm->
sh * ( glcomm->
sy - (double)sy - 1 ) / glcomm->
h;
372 tx, ty, glcomm->
srw, glcomm->
srh, NULL, 0. );
376 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.current_fbo );
388 char buf[STRMAX_SHORT];
399 ship_renderGfxStore( fbo, s, size, dir, updown, glow );
401 glDeleteFramebuffers( 1, &fbo );
402 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.current_fbo );
406 snprintf( buf,
sizeof( buf ),
"%s_fbo_gfx_store_%d", s->
name, size );
408 gltex->
flags |= OPENGL_TEX_VFLIP;
422 GLuint fbo, tex, depth_tex;
423 char buf[STRMAX_SHORT];
426 fbosize = ceil( size /
gl_screen.scale );
434 glBindFramebuffer( GL_FRAMEBUFFER, fbo );
435 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
437 if ( s->
gfx_3d != NULL ) {
438 Lighting L = ( Lscene == NULL ) ? L_default : *Lscene;
440 double t = SDL_GetTicks() / 1000.;
444 snprintf( buf,
sizeof( buf ),
"%s_fbo_gfx_comm_%d", s->
name, size );
454 if ( fabs( tilt ) > DOUBLE_TOL ) {
459 mat4_rotate( &Hlight, dir + M_PI_2, 0.0, 1.0, 0.0 );
460 gltf_lightTransform( &L, &Hlight );
469 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.fbo[2] );
470 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
473 glBindFramebuffer( GL_READ_FRAMEBUFFER,
gl_screen.fbo[2] );
474 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, fbo );
475 glBlitFramebuffer( 0, 0, rendersize, rendersize, 0, fbosize, fbosize, 0,
476 GL_COLOR_BUFFER_BIT, GL_LINEAR );
481 snprintf( buf,
sizeof( buf ),
"%s_fbo_gfx_comm_%d", s->
gfx_comm, size );
483 glcomm->
flags &= ~OPENGL_TEX_VFLIP;
485 scale =
MIN( size / glcomm->
w, size / glcomm->
h );
486 w = scale * glcomm->
w;
487 h = scale * glcomm->
h;
489 0., 0., 1., 1., NULL, 0. );
493 WARN( _(
"Unable to render comm graphic for ship '%s'!" ), s->
name );
495 glDeleteFramebuffers( 1, &fbo );
496 glDeleteTextures( 1, &depth_tex );
497 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.current_fbo );
502 gltex->
flags |= OPENGL_TEX_VFLIP;
528 switch ( s->
class ) {
529 case SHIP_CLASS_YACHT:
530 case SHIP_CLASS_SCOUT:
531 case SHIP_CLASS_INTERCEPTOR:
534 case SHIP_CLASS_COURIER:
535 case SHIP_CLASS_FIGHTER:
536 case SHIP_CLASS_BOMBER:
539 case SHIP_CLASS_FREIGHTER:
540 case SHIP_CLASS_CORVETTE:
543 case SHIP_CLASS_DESTROYER:
544 case SHIP_CLASS_ARMOURED_TRANSPORT:
547 case SHIP_CLASS_BULK_FREIGHTER:
548 case SHIP_CLASS_CRUISER:
551 case SHIP_CLASS_BATTLESHIP:
552 case SHIP_CLASS_CARRIER:
570 unsigned int flags = OPENGL_TEX_MIPMAPS | OPENGL_TEX_VFLIP;
573 flags |= OPENGL_TEX_MAPTRANS;
605 ThreadQueue *tq = vpool_create();
606 SDL_GL_MakeCurrent(
gl_screen.window, NULL );
610 if ( !ship_isFlag( s, SHIP_NEEDSGFX ) )
612 vpool_enqueue( tq, (
int ( * )(
void * ))
ship_gfxLoad, s );
613 ship_rmFlag( s, SHIP_NEEDSGFX );
631 const char *delim, *base_path;
632 const char *ext =
".webp";
643 delim = strchr( buf,
'_' );
644 base = delim == NULL ? strdup( buf ) :
strndup( buf, delim - buf );
648 snprintf( str,
sizeof( str ), SHIP_3DGFX_PATH
"%s/%s.gltf", base_path, buf );
649 if ( PHYSFS_exists( str ) ) {
651 s->
gfx_3d = gltf_loadFromFile( str );
657 ship_setFlag( s, SHIP_3DTRAILS );
665 vec3_scale( &trail.
pos, s->
size * 0.5 );
678 ship_setFlag( s, SHIP_3DMOUNTS );
680 WARN( _(
"Number of 3D weapon mounts from GLTF file for ship '%s' "
682 "number of ship weapons! Got %d, expected at least %d." ),
689 vec3_scale( &sm->
pos, s->
size * 0.5 );
696 snprintf( str,
sizeof( str ),
"%s", buf );
698 snprintf( str,
sizeof( str ), SHIP_GFX_PATH
"%s/%s%s", base, buf, ext );
699 if ( !PHYSFS_exists( str ) ) {
701 snprintf( str,
sizeof( str ), SHIP_GFX_PATH
"%s/%s%s", base, buf,
726 snprintf( str,
sizeof( str ), SHIP_GFX_PATH
"%s/%s" SHIP_ENGINE "%s",
730 WARN( _(
"Ship '%s' does not have an engine sprite (%s)." ), s->
name,
739 WARN( (
"Mismatch between 'size' and 'gfx_space' sprite size for ship "
740 "'%s'! 'size' should be %.0f!" ),
760 if ( temp->
gfx_3d != NULL )
761 snprintf( file,
sizeof( file ),
"%s%s.xml", SHIP_POLYGON_PATH3D, buf );
763 snprintf( file,
sizeof( file ),
"%s%s.xml", SHIP_POLYGON_PATH, buf );
766 if ( !PHYSFS_exists( file ) ) {
767 WARN( _(
"%s xml collision polygon does not exist! Please use the "
768 "script '%s' found in Naev's main repository." ),
769 file,
"utils/polygonize.py" );
778 node = doc->xmlChildrenNode;
779 if ( node == NULL ) {
781 WARN( _(
"Malformed %s file: does not contain elements" ), file );
786 if ( xml_isNode( node,
"polygons" ) )
788 }
while ( xml_nextNode( node ) );
804 OutfitSlotType type, xmlNodePtr node )
806 OutfitSlotSize base_size;
812 xmlr_attr_strd( node,
"size", buf );
816 WARN( _(
"Ship '%s' has undefined slot size, setting to '%s'" ),
817 temp->
name,
"Small" );
818 base_size = OUTFIT_SLOT_SIZE_LIGHT;
823 if ( type == OUTFIT_SLOT_WEAPON ) {
824 xmlr_attr_float( node,
"x", slot->
mount.
pos.v[0] );
825 xmlr_attr_float( node,
"y", slot->
mount.
pos.v[1] );
829 xmlr_attr_float( node,
"h", slot->
mount.
pos.v[2] );
833 xmlr_attr_strd( node,
"prop", buf );
858 xmlr_attr_int_def( node,
"locked", slot->
locked, slot->
locked );
861 xmlr_attr_strd( node,
"name", slot->
name );
864 buf = xml_get( node );
868 WARN( _(
"Ship '%s' has default outfit '%s' which does not exist." ),
879 WARN( _(
"Ship '%s' has required slot without a default outfit." ),
895 xmlNodePtr parent, node;
900 if ( ( !firstpass ) && ( temp->
inherits == NULL ) )
909 parent = doc->xmlChildrenNode;
910 if ( parent == NULL ) {
912 WARN( _(
"Malformed %s file: does not contain elements" ), filename );
917 memset( temp, 0,
sizeof(
Ship ) );
936 xmlr_attr_strd_free( parent,
"name", temp->
name );
937 if ( temp->
name == NULL )
938 WARN( _(
"Ship in %s has invalid or no name" ), SHIP_DATA_PATH );
941 xmlr_attr_strd_free( parent,
"inherits", temp->
inherits );
949 parent = doc->xmlChildrenNode;
950#define STRDUP_( x ) ( ( x == NULL ) ? NULL : strdup( x ) )
951#define ARRAYDUP_( x, y ) \
953 for ( int i = 0; i < array_size( y ); i++ ) \
954 array_push_back( &x, y[i] ); \
990 while ( ll != NULL ) {
1005 temp->
turn *= 180. / M_PI;
1009 node = parent->xmlChildrenNode;
1013 xml_onlyNodes( node );
1015 if ( xml_isNode( node,
"class" ) ) {
1016 xmlr_attr_strd_free( node,
"display", temp->
class_display );
1020 if ( xml_isNode( node,
"gfx" ) || xml_isNode( node,
"GFX" ) ) {
1021 const char *str = xml_get( node );
1023 if ( xml_isNode( node,
"GFX" ) )
1024 WARN( _(
"Ship '%s': using <GFX> instead of <gfx>!" ), temp->
name );
1027 if ( str == NULL ) {
1028 WARN( _(
"Ship '%s' has NULL tag '%s'!" ), temp->
name,
"gfx" );
1036 xmlr_attr_float_def( node,
"size", temp->
size, 1 );
1037 xmlr_attr_int_def( node,
"sx", temp->sx, 8 );
1038 xmlr_attr_int_def( node,
"sy", temp->sy, 8 );
1039 xmlr_attr_strd_free( node,
"comm", temp->
gfx_comm );
1040 xmlr_attr_int( node,
"noengine", temp->
noengine );
1041 xmlr_attr_strd_free( node,
"polygon", temp->
polygon_path );
1048 if ( xml_isNode( node,
"faction" ) ) {
1053 if ( xml_isNode( node,
"gfx_overlays" ) ) {
1054 xmlNodePtr cur = node->children;
1058 xml_onlyNodes( cur );
1059 if ( xml_isNode( cur,
"gfx_overlay" ) )
1062 1, OPENGL_TEX_MIPMAPS ) );
1063 }
while ( xml_nextNode( cur ) );
1067 if ( xml_isNode( node,
"sound" ) ) {
1068 xmlr_attr_float_def( node,
"pitch", temp->
engine_pitch, 1. );
1072 if ( xml_isNode( node,
"base_type" ) ) {
1073 const char *nstr = xml_get( node );
1074 xmlr_attr_strd_free( node,
"path", temp->
base_path );
1076 temp->
base_type = ( nstr != NULL ) ? strdup( nstr ) : NULL;
1079 xmlr_float( node,
"time_mod", temp->
dt_default );
1080 xmlr_long( node,
"price", temp->
price );
1081 xmlr_strd_free( node,
"license", temp->
license );
1082 xmlr_strd_free( node,
"cond", temp->
cond );
1083 xmlr_strd_free( node,
"condstr", temp->
condstr );
1084 xmlr_strd_free( node,
"fabricator", temp->
fabricator );
1085 xmlr_strd_free( node,
"description", temp->
description );
1086 xmlr_strd_free( node,
"desc_extra", temp->
desc_extra );
1087 xmlr_int( node,
"points", temp->
points );
1088 xmlr_int( node,
"rarity", temp->
rarity );
1089 if ( xml_isNode( node,
"lua" ) ) {
1090 const char *nstr = xml_get( node );
1091 if ( nstr == NULL ) {
1092 WARN( _(
"Ship '%s' has invalid '%s' node." ), temp->
name,
"lua" );
1096 if ( nstr[0] ==
'/' )
1099 SDL_asprintf( &temp->
lua_file, SHIP_DATA_LUA_PATH
"%s", nstr );
1103 if ( xml_isNode( node,
"flags" ) ) {
1104 xmlNodePtr cur = node->children;
1106 xml_onlyNodes( cur );
1107 if ( xml_isNode( cur,
"noplayer" ) ) {
1108 ship_setFlag( temp, SHIP_NOPLAYER );
1111 if ( xml_isNode( cur,
"noescort" ) ) {
1112 ship_setFlag( temp, SHIP_NOESCORT );
1115 if ( xml_isNode( cur,
"unique" ) ) {
1116 ship_setFlag( temp, SHIP_UNIQUE );
1120 WARN( _(
"Ship '%s' has unknown flags node '%s'." ), temp->
name,
1122 }
while ( xml_nextNode( cur ) );
1126 if ( xml_isNode( node,
"trail_generator" ) ) {
1128 xmlr_attr_float( node,
"x", trail.
pos.v[0] );
1129 xmlr_attr_float( node,
"y", trail.
pos.v[1] );
1130 xmlr_attr_float( node,
"h", trail.
pos.v[2] );
1131 xmlr_attr_int_def( node,
"always_under", trail.
flags,
1132 SHIP_TRAIL_ALWAYS_UNDER );
1133 buf = xml_get( node );
1142 if ( xml_isNode( node,
"movement" ) ) {
1143 xmlNodePtr cur = node->children;
1145 xml_onlyNodes( cur );
1146 xmlr_float( cur,
"accel", temp->
accel );
1147 xmlr_float( cur,
"turn", temp->
turn );
1148 xmlr_float( cur,
"speed", temp->
speed );
1151 WARN( _(
"Ship '%s' has unknown movement node '%s'." ), temp->
name,
1153 }
while ( xml_nextNode( cur ) );
1156 if ( xml_isNode( node,
"health" ) ) {
1157 xmlNodePtr cur = node->children;
1159 xml_onlyNodes( cur );
1160 xmlr_float( cur,
"absorb", temp->
dmg_absorb );
1161 xmlr_float( cur,
"armour", temp->
armour );
1163 xmlr_float( cur,
"shield", temp->
shield );
1165 xmlr_float( cur,
"energy", temp->
energy );
1169 WARN( _(
"Ship '%s' has unknown health node '%s'." ), temp->
name,
1171 }
while ( xml_nextNode( cur ) );
1174 if ( xml_isNode( node,
"characteristics" ) ) {
1175 xmlNodePtr cur = node->children;
1177 xml_onlyNodes( cur );
1178 xmlr_int( cur,
"crew", temp->
crew );
1179 xmlr_float( cur,
"mass", temp->
mass );
1180 xmlr_float( cur,
"cpu", temp->
cpu );
1181 xmlr_int( cur,
"fuel", temp->
fuel );
1183 xmlr_float( cur,
"cargo", temp->
cap_cargo );
1186 WARN( _(
"Ship '%s' has unknown characteristic node '%s'." ),
1187 temp->
name, cur->name );
1188 }
while ( xml_nextNode( cur ) );
1191 if ( xml_isNode( node,
"slots" ) ) {
1202 xmlNodePtr cur = node->children;
1204 xml_onlyNodes( cur );
1205 if ( xml_isNode( cur,
"structure" ) )
1207 OUTFIT_SLOT_STRUCTURE, cur );
1208 else if ( xml_isNode( cur,
"utility" ) )
1210 OUTFIT_SLOT_UTILITY, cur );
1211 else if ( xml_isNode( cur,
"weapon" ) )
1213 OUTFIT_SLOT_WEAPON, cur );
1214 else if ( xml_isNode( cur,
"intrinsic" ) ) {
1217 WARN( _(
"Ship '%s' has unknown intrinsic outfit '%s'" ),
1218 temp->
name, xml_get( cur ) );
1226 WARN( _(
"Ship '%s' has unknown slot node '%s'." ), temp->
name,
1228 }
while ( xml_nextNode( cur ) );
1236 if ( xml_isNode( node,
"stats" ) ) {
1237 xmlNodePtr cur = node->children;
1239 if ( temp->
stats != NULL ) {
1245 xml_onlyNodes( cur );
1252 WARN( _(
"Ship '%s' has unknown stat '%s'." ), temp->
name,
1254 }
while ( xml_nextNode( cur ) );
1262 if ( temp->
stats != NULL ) {
1278 if ( xml_isNode( node,
"tags" ) ) {
1279 xmlNodePtr cur = node->children;
1281 free( temp->
tags[i] );
1285 xml_onlyNodes( cur );
1286 if ( xml_isNode( cur,
"tag" ) ) {
1287 const char *tmp = xml_get( cur );
1292 WARN( _(
"Ship '%s' has unknown node in tags '%s'." ), temp->
name,
1294 }
while ( xml_nextNode( cur ) );
1299 if ( xml_isNode( node,
"mission" ) )
1302 DEBUG( _(
"Ship '%s' has unknown node '%s'." ), temp->
name, node->name );
1303 }
while ( xml_nextNode( node ) );
1307 temp->
turn *= M_PI / 180.;
1311 WARN( _(
"Ship '%s' has inexistent license requirement '%s'!" ),
1315#define MELEMENT( o, s ) \
1317 WARN( _( "Ship '%s' missing '%s' element" ), temp->name, s )
1318 MELEMENT( temp->
name == NULL,
"name" );
1319 MELEMENT( temp->
base_type == NULL,
"base_type" );
1320 MELEMENT( ( temp->
gfx_path == NULL ),
"GFX" );
1321 MELEMENT( temp->
size <= 0.,
"GFX.size" );
1322 MELEMENT( temp->
class == SHIP_CLASS_NULL,
"class" );
1323 MELEMENT( temp->
points == 0,
"points" );
1324 MELEMENT( temp->
price == 0,
"price" );
1325 MELEMENT( temp->
dt_default <= 0.,
"time_mod" );
1326 MELEMENT( temp->
fabricator == NULL,
"fabricator" );
1327 MELEMENT( temp->
description == NULL,
"description" );
1328 MELEMENT( temp->
armour == 0.,
"armour" );
1329 MELEMENT( ( temp->
cond != NULL ) && ( temp->
condstr == NULL ),
"condstr" );
1330 MELEMENT( ( temp->
cond == NULL ) && ( temp->
condstr != NULL ),
"cond" );
1339 MELEMENT( temp->
crew == 0,
"crew" );
1340 MELEMENT( temp->
mass == 0.,
"mass" );
1355 double fw,
double fh,
double engine_glow,
1356 double t,
const glColour *
c,
1358 int blit,
unsigned int flags )
1360 double scale = ship_aa_scale * size;
1362 mat4 projection, tex_mat;
1363 GLint sbuffer = ceil( scale );
1365 glBindFramebuffer( GL_FRAMEBUFFER, ship_fbo[0] );
1368 glEnable( GL_SCISSOR_TEST );
1369 glScissor( 0, 0, sbuffer, sbuffer );
1370 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1371 glDisable( GL_SCISSOR_TEST );
1374 projection =
mat4_ortho( 0., fw, 0, fh, -1., 1. );
1375 mat4_scale_xy( &projection, scale *
gl_screen.scale,
1378 mat4_scale_xy( &tex_mat, scale / ship_fbos, scale / ship_fbos );
1381 if ( ( engine_glow > 0. ) && ( obj->
scene_engine >= 0 ) ) {
1382 if ( engine_glow >= 1. ) {
1383 gltf_renderScene( ship_fbo[0], obj, obj->
scene_engine, H, t, scale,
1387 glEnable( GL_SCISSOR_TEST );
1388 glBindFramebuffer( GL_FRAMEBUFFER, ship_fbo[2] );
1389 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1390 glBindFramebuffer( GL_FRAMEBUFFER, ship_fbo[1] );
1391 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1392 glDisable( GL_SCISSOR_TEST );
1395 gltf_renderScene( ship_fbo[1], obj, obj->
scene_body, H, t, scale, L );
1396 gltf_renderScene( ship_fbo[2], obj, obj->
scene_engine, H, t, scale,
1400 glBindFramebuffer( GL_FRAMEBUFFER, ship_fbo[0] );
1402 &projection, &tex_mat, &cWhite );
1405 GLint blitsize = scale;
1406 glBindFramebuffer( GL_READ_FRAMEBUFFER, ship_fbo[1] );
1407 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, ship_fbo[0] );
1408 glBlitFramebuffer( 0, 0, blitsize, blitsize, 0, 0, blitsize, blitsize,
1409 GL_DEPTH_BUFFER_BIT, GL_NEAREST );
1415 gltf_renderScene( ship_fbo[0], obj, obj->
scene_body, H, t, scale, L );
1420 glBindFramebuffer( GL_FRAMEBUFFER, ship_fbo[1] );
1421 glEnable( GL_SCISSOR_TEST );
1422 glScissor( 0, 0, sbuffer + ship_aa_scale_base,
1423 sbuffer + ship_aa_scale_base );
1424 glClear( GL_COLOR_BUFFER_BIT );
1425 glDisable( GL_SCISSOR_TEST );
1427 glUseProgram( shaders.texture_sharpen.program );
1428 glBindTexture( GL_TEXTURE_2D, ship_tex[0] );
1430 glEnableVertexAttribArray( shaders.texture_sharpen.vertex );
1435 gl_uniformColour( shaders.texture_sharpen.colour,
c );
1436 gl_uniformMat4( shaders.texture_sharpen.projection, &projection );
1437 gl_uniformMat4( shaders.texture_sharpen.tex_mat, &tex_mat );
1440 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1443 glDisableVertexAttribArray( shaders.texture_sharpen.vertex );
1452 GLint sin = sbuffer + (GLint)ship_aa_scale_base;
1453 GLint sout = ceil( size /
gl_screen.scale ) + 1;
1454 glBindFramebuffer( GL_READ_FRAMEBUFFER, ship_fbo[1] );
1455 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, fbo );
1456 if ( flags & OPENGL_TEX_VFLIP ) {
1457 glBlitFramebuffer( 0, 0, sin, sin, 0, sout, sout, 0,
1458 GL_COLOR_BUFFER_BIT, GL_LINEAR );
1460 glBindFramebuffer( GL_READ_FRAMEBUFFER, ship_fbo[0] );
1461 glBlitFramebuffer( 0, 0, sin, sin, 0, sout, sout, 0,
1462 GL_DEPTH_BUFFER_BIT, GL_NEAREST );
1464 glBlitFramebuffer( 0, 0, sin, sin, 0, 0, sout, sout,
1465 GL_COLOR_BUFFER_BIT, GL_LINEAR );
1466 glBindFramebuffer( GL_READ_FRAMEBUFFER, ship_fbo[0] );
1467 glBlitFramebuffer( 0, 0, sin, sin, 0, 0, sout, sout,
1468 GL_DEPTH_BUFFER_BIT, GL_NEAREST );
1471 glBindFramebuffer( GL_FRAMEBUFFER, fbo );
1473 if ( flags & OPENGL_TEX_VFLIP ) {
1474 tex_mat.m[1][1] = -1.;
1475 tex_mat.m[3][1] = 0.5;
1480 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.current_fbo );
1490 double dir,
double engine_glow,
double tilt,
1491 double r,
int sx,
int sy,
const glColour *
c,
1497 if ( s->
gfx_3d != NULL ) {
1502 if ( fabs( tilt ) > DOUBLE_TOL ) {
1517 glBindFramebuffer( GL_FRAMEBUFFER, fbo );
1523 glEnable( GL_SCISSOR_TEST );
1526 glClear( GL_COLOR_BUFFER_BIT );
1527 glDisable( GL_SCISSOR_TEST );
1530 tx = sa->
sw * (double)( sx ) / sa->
w;
1531 ty = sa->
sh * ( sa->
sy - (double)sy - 1 ) / sa->
h;
1533 tmpm = gl_view_matrix;
1534 gl_view_matrix =
mat4_ortho( 0., fw, 0, fh, -1., 1. );
1537 tx, ty, sa->
srw, sa->
srh,
c );
1539 gl_view_matrix = tmpm;
1541 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.current_fbo );
1572 Uint32 time = SDL_GetTicks();
1574 ThreadQueue *tq = vpool_create();
1588 for (
int i = 0; i < nfiles; i++ ) {
1594 free( ship_files[i] );
1599 SDL_GL_MakeCurrent(
gl_screen.window, NULL );
1600 for (
int i = 0; i <
array_size( shipdata ); i++ )
1604 vpool_cleanup( tq );
1608 for (
int i = 0; i <
array_size( shipdata ); i++ ) {
1631 WARN( _(
"Duplicated ship name '%s' detected!" ),
ship_stack[i].name );
1641 max_size =
MAX( max_size, s->
size );
1648 if ( dat == NULL ) {
1649 WARN( _(
"Ship '%s' failed to read Lua '%s'!" ), s->
name,
1662 if ( nlua_dobufenv( env, dat, sz, s->
lua_file ) != 0 ) {
1663 WARN( _(
"Ship '%s' Lua error:\n%s" ), s->
name,
1664 lua_tostring(
naevL, -1 ) );
1665 lua_pop(
naevL, 1 );
1674 nlua_getenv(
naevL, env,
"update_dt" );
1675 if ( !lua_isnoneornil(
naevL, -1 ) )
1677 lua_pop(
naevL, 1 );
1692 lua_pushnil(
naevL );
1694 if ( nlua_pcall( s->
lua_env, 2, 1 ) ) {
1695 lua_pop(
naevL, 1 );
1696 }
else if ( lua_isnoneornil(
naevL, -1 ) ) {
1698 lua_pop(
naevL, 1 );
1701 lua_pop(
naevL, 1 );
1707 if ( conf.devmode ) {
1708 DEBUG( n_(
"Loaded %d Ship in %.3f s",
"Loaded %d Ships in %.3f s",
1720void ships_resize(
void )
1722 if ( ship_aa_scale > 0. ) {
1723 for (
int i = 0; i < SHIP_FBO; i++ ) {
1724 glDeleteFramebuffers( 1, &ship_fbo[i] );
1725 glDeleteTextures( 1, &ship_tex[i] );
1726 glDeleteTextures( 1, &ship_texd[i] );
1731 ship_aa_scale = ship_aa_scale_base /
gl_screen.scale;
1732 ship_fbos = ceil( ship_aa_scale * max_size );
1733 for (
int i = 0; i < SHIP_FBO; i++ ) {
1734 gl_fboCreate( &ship_fbo[i], &ship_tex[i], ship_fbos, ship_fbos );
1735 gl_fboAddDepth( ship_fbo[i], &ship_texd[i], ship_fbos, ship_fbos );
1746 for (
int i = 0; i < SHIP_FBO; i++ ) {
1747 glDeleteFramebuffers( 1, &ship_fbo[i] );
1748 glDeleteTextures( 1, &ship_tex[i] );
1749 glDeleteTextures( 1, &ship_texd[i] );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
void poly_load(CollPoly *polygon, xmlNodePtr base, const char *name)
Loads a polygon from an xml node.
const glColour * faction_colour(int f)
Gets the colour of the faction.
int faction_get(const char *name)
Gets a faction ID by name.
mat4 mat4_identity(void)
Creates an identity matrix.
void mat4_rotate(mat4 *m, double angle, double x, double y, double z)
Multiplies the given matrix by a rotation. (Follows the right-hand rule.)
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
void naev_renderLoadscreen(void)
Renders the loadscreen if necessary.
int naev_shouldRenderLoadscreen(void)
Whether or not we want to render the loadscreen.
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
int nlua_refenvtype(nlua_env env, const char *name, int type)
Gets the reference of a global in a lua environment if it matches a type.
int nlua_loadCamera(nlua_env env)
Loads the camera library.
int nlua_loadGFX(nlua_env env)
Loads the graphics library.
const Ship ** lua_pushship(lua_State *L, const Ship *ship)
Pushes a ship on the stack.
char * strndup(const char *s, size_t n)
Return a pointer to a new string, which is a duplicate of the string s (or, if necessary,...
glTexture * xml_parseTexture(xmlNodePtr node, const char *path, int defsx, int defsy, const unsigned int flags)
Parses a texture handling the sx and sy elements.
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
void gl_renderShader(double x, double y, double w, double h, double r, const SimpleShader *shd, const glColour *c, int center)
Renders a simple shader.
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.
void gl_renderTextureInterpolate(const glTexture *ta, const glTexture *tb, double inter, double x, double y, double w, double h, double tx, double ty, double tw, double th, const glColour *c)
Texture blitting backend for interpolated texture.
void gl_renderTextureRawH(GLuint texture, const mat4 *projection, const mat4 *tex_mat, const glColour *c)
Texture blitting backend.
void gl_renderTextureInterpolateRawH(GLuint ta, GLuint tb, double inter, const mat4 *projection, const mat4 *tex_mat, const glColour *c)
Texture blitting backend for interpolated texture.
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
glTexture * gl_newSprite(const char *path, const int sx, const int sy, const unsigned int flags)
Loads the texture immediately, but also sets it as a sprite.
USE_RESULT glTexture * gl_rawTexture(const char *name, GLuint texid, double w, double h)
Creates a texture from a raw opengl index.
int gl_fboCreate(GLuint *fbo, GLuint *tex, GLsizei width, GLsizei height)
Creates a framebuffer and its associated texture.
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
int gl_fboAddDepth(GLuint fbo, GLuint *tex, GLsizei width, GLsizei height)
Adds a depth attachment to an FBO.
void gl_getSpriteFromDir(int *x, int *y, int sx, int sy, double dir)
Sets x and y to be the appropriate sprite for glTexture using dir.
void gl_freeTexture(glTexture *texture)
Frees a texture.
void gl_vboActivateAttribOffset(gl_vbo *vbo, GLuint index, GLuint offset, GLint size, GLenum type, GLsizei stride)
Activates a VBO's offset.
const Outfit * outfit_get(const char *name)
Gets an outfit by name.
OutfitSlotSize outfit_toSlotSize(const char *s)
Gets the outfit slot size from a human readable string.
int outfit_licenseExists(const char *name)
Checks to see if a license exists.
void outfit_freeSlot(OutfitSlot *s)
Frees an outfit slot.
int ship_size(const Ship *s)
Gets the size of the ship.
ShipClass ship_classFromString(const char *str)
Gets the machine ship class identifier from a human readable string.
static int ship_parse(Ship *temp, const char *filename, int firstpass)
Extracts the in-game ship from an XML node.
static int ship_parseSlot(Ship *temp, ShipOutfitSlot *slot, OutfitSlotType type, xmlNodePtr node)
Parses a slot for a ship.
static int ship_loadSpaceImage(Ship *temp, const char *str, int sx, int sy)
Loads the space graphics for a ship from an image.
const char * ship_class(const Ship *s)
Gets the ship's class name in human readable form.
static int ship_loadPLG(Ship *temp, const char *buf)
Loads the collision polygon for a ship.
static void ship_renderFramebuffer3D(const Ship *s, GLuint fbo, double size, double fw, double fh, double engine_glow, double t, const glColour *c, const Lighting *L, const mat4 *H, int blit, unsigned int flags)
Renders a 3D ship to a framebuffer.
const char * ship_classDisplay(const Ship *s)
Gets the ship's display class in human readable form.
credits_t ship_basePrice(const Ship *s)
Gets the ship's base price (no outfits).
static int ship_parseThread(void *ptr)
Wrapper for threaded loading.
credits_t ship_buyPrice(const Ship *s)
The ship buy price, includes default outfits.
double ship_maxSize(void)
Gets the maximum size of a ship.
const Ship * ship_getW(const char *name)
Gets a ship based on its name without warning.
int ships_load(void)
Loads all the ships in the data files.
static int ship_cmp(const void *p1, const void *p2)
Compares two ship pointers for qsort.
const Ship * ship_getAll(void)
Gets the array (array.h) of all ships.
int ship_gfxLoadNeeded(void)
Tries to load the graphics for all ships that need it.
static int ship_loadEngineImage(Ship *temp, const char *str, int sx, int sy)
Loads the space graphics for a ship from an image.
void ships_free(void)
Frees all the ships.
glTexture * ship_gfxComm(const Ship *s, int size, double tilt, double dir, const Lighting *Lscene)
Loads the ship's comm graphic.
int ship_compareTech(const void *arg1, const void *arg2)
Comparison function for qsort().
const char * ship_classToString(ShipClass class)
Gets the ship class name in human readable form.
int ship_gfxLoaded(const Ship *s)
Checks to see if a ship has loaded graphics.
int ship_gfxAnimated(const Ship *s)
Returns whether or not the ship has animated graphics.
void ship_renderFramebuffer(const Ship *s, GLuint fbo, double fw, double fh, double dir, double engine_glow, double tilt, double r, int sx, int sy, const glColour *c, const Lighting *L)
Renders a ship to a framebuffer.
glTexture * ship_gfxStore(const Ship *s, int size, double dir, double updown, double glow)
Get the store gfx.
const Ship * ship_get(const char *name)
Gets a ship based on its name.
const char * ship_existsCase(const char *name)
Checks to see if an ship exists matching name (case insensitive).
int ship_gfxLoad(Ship *s)
Loads the graphics for a ship if necessary.
int ss_statsListDesc(const ShipStatList *ll, char *buf, int len, int newline)
Writes the ship statistics description.
void ss_free(ShipStatList *ll)
Frees a list of ship stats.
int ss_statsMergeFromList(ShipStats *stats, const ShipStatList *list)
Updates a stat structure from a stat list.
int ss_statsInit(ShipStats *stats)
Initializes a stat structure.
int ss_check(void)
Checks for validity.
ShipStatList * ss_listFromXML(xmlNodePtr node)
Creates a shipstat list element from an xml node.
int ss_sort(ShipStatList **ll)
Sorts the ship stats, useful if doing saving stuff.
int sp_locked(unsigned int spid)
Gets whether or not a slot property is locked.
unsigned int sp_get(const char *name)
Gets the id of a slot property.
int sp_required(unsigned int spid)
Gets whether or not a slot property is required.
int sp_exclusive(unsigned int spid)
Gets whether or not a slot property is exclusive.
int sp_visible(unsigned int spid)
Whether or not the slot should be visible even if locked.
int sound_get(const char *name)
Gets the buffer to sound of name.
const TrailSpec * trailSpec_get(const char *name)
Gets a trail spec by name.
Defines a complete object.
A ship outfit, depends radically on the type.
Represents a ship weapon mount point.
Represents relative ship statistics as a linked list.
struct ShipStatList_ * next
Structure for threaded loading.
const TrailSpec * trail_spec
ShipOutfitSlot * outfit_utility
Outfit const ** outfit_intrinsic
ShipOutfitSlot * outfit_weapon
ShipTrailEmitter * trail_emitters
glTexture ** gfx_overlays
ShipOutfitSlot * outfit_structure
Abstraction for rendering sprite sheets.