Add BRX1 extension format and native in-BSP lightmap page sizes
q3map2 changes: - BRX1 backward-compatible BSP extension (always v46, extra lumps after header with magic + overlap detection) - -lightmapsize N stores pages natively in BSP via EXT_LUMP_LIGHTMAP_INFO - -extlmhacksize N unchanged (legacy external TGA + custom shaders) - SH grid moved from v47 lump 18 to BRX1 EXT_LUMP_LIGHTGRID_SH - Removed v47 version logic - MSVC fix: noexcept move ctor for entity_t (std::list move not noexcept)
This commit is contained in:
parent
301959d0ae
commit
aae67c1fb5
4 changed files with 182 additions and 107 deletions
|
|
@ -61,16 +61,8 @@
|
||||||
#define LUMP_LIGHTMAPS 14
|
#define LUMP_LIGHTMAPS 14
|
||||||
#define LUMP_LIGHTGRID 15
|
#define LUMP_LIGHTGRID 15
|
||||||
#define LUMP_VISIBILITY 16
|
#define LUMP_VISIBILITY 16
|
||||||
#define LUMP_ADVERTISEMENTS 17
|
|
||||||
#define LUMP_LIGHTGRID_SH 18
|
|
||||||
|
|
||||||
#define HEADER_LUMPS_V46 17 /* standard Q3: lumps 0-16, header = 144 bytes */
|
#define HEADER_LUMPS_V46 17 /* standard Q3: lumps 0-16, header = 144 bytes */
|
||||||
#define HEADER_LUMPS_V47 19 /* extended: lumps 0-18, header = 160 bytes */
|
|
||||||
#define HEADER_LUMPS_MAX 19 /* max for internal use */
|
|
||||||
|
|
||||||
#define IBSP_VERSION_V46 46
|
#define IBSP_VERSION_V46 46
|
||||||
#define IBSP_VERSION_V47 47
|
|
||||||
|
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
struct ibspHeader_v46_t
|
struct ibspHeader_v46_t
|
||||||
|
|
@ -80,20 +72,8 @@ struct ibspHeader_v46_t
|
||||||
bspLump_t lumps[ HEADER_LUMPS_V46 ];
|
bspLump_t lumps[ HEADER_LUMPS_V46 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ibspHeader_v47_t
|
/* internal header -- uses v46 lump count */
|
||||||
{
|
using ibspHeader_t = ibspHeader_v46_t;
|
||||||
char ident[ 4 ];
|
|
||||||
int version;
|
|
||||||
bspLump_t lumps[ HEADER_LUMPS_V47 ];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* internal header -- always uses max lump count for convenience */
|
|
||||||
struct ibspHeader_t
|
|
||||||
{
|
|
||||||
char ident[ 4 ];
|
|
||||||
int version;
|
|
||||||
bspLump_t lumps[ HEADER_LUMPS_MAX ];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -238,30 +218,21 @@ void LoadIBSPFile( const char *filename ){
|
||||||
/* load the file */
|
/* load the file */
|
||||||
MemBuffer file = LoadFile( filename );
|
MemBuffer file = LoadFile( filename );
|
||||||
|
|
||||||
/* read ident and version to determine header size */
|
/* read ident and version */
|
||||||
const byte *data = (const byte *)file.data();
|
const byte *data = (const byte *)file.data();
|
||||||
|
const size_t fileSize = file.size();
|
||||||
const int version = LittleLong( *(const int *)( data + 4 ) );
|
const int version = LittleLong( *(const int *)( data + 4 ) );
|
||||||
|
|
||||||
/* make sure it matches the format we're trying to load */
|
/* make sure it matches the format we're trying to load */
|
||||||
if ( !force && memcmp( data, g_game->bspIdent, 4 ) ) {
|
if ( !force && memcmp( data, g_game->bspIdent, 4 ) ) {
|
||||||
Error( "%s is not a %s file", filename, g_game->bspIdent );
|
Error( "%s is not a %s file", filename, g_game->bspIdent );
|
||||||
}
|
}
|
||||||
if ( !force && version != IBSP_VERSION_V46 && version != IBSP_VERSION_V47 ) {
|
if ( !force && version != IBSP_VERSION_V46 ) {
|
||||||
Error( "%s is version %d, expected %d or %d", filename, version, IBSP_VERSION_V46, IBSP_VERSION_V47 );
|
Error( "%s is version %d, expected %d", filename, version, IBSP_VERSION_V46 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine lump count from version */
|
|
||||||
const int numLumps = ( version == IBSP_VERSION_V47 ) ? HEADER_LUMPS_V47 : HEADER_LUMPS_V46;
|
|
||||||
|
|
||||||
/* CopyLump uses (byte*)header + offset to access file data,
|
|
||||||
so we overlay a bspHeader_t at the file buffer start and
|
|
||||||
copy/swap the lump directory into it. bspHeader_t has lumps[100]
|
|
||||||
so it can hold all our lumps. */
|
|
||||||
bspHeader_t *header = (bspHeader_t *)file.data();
|
bspHeader_t *header = (bspHeader_t *)file.data();
|
||||||
/* swap just the lump directory entries we have */
|
SwapBlock( (int *)( (byte *)header + 8 ), HEADER_LUMPS_V46 * sizeof( bspLump_t ) );
|
||||||
SwapBlock( (int *)( (byte *)header + 8 ), numLumps * sizeof( bspLump_t ) );
|
|
||||||
/* note: lumps beyond numLumps are not zeroed -- they overlap file data
|
|
||||||
in the buffer. We only access extended lumps under version checks. */
|
|
||||||
|
|
||||||
/* load/convert standard lumps (0-16) */
|
/* load/convert standard lumps (0-16) */
|
||||||
CopyLump( header, LUMP_SHADERS, bspShaders );
|
CopyLump( header, LUMP_SHADERS, bspShaders );
|
||||||
|
|
@ -282,33 +253,81 @@ void LoadIBSPFile( const char *filename ){
|
||||||
CopyLump( header, LUMP_ENTITIES, bspEntData );
|
CopyLump( header, LUMP_ENTITIES, bspEntData );
|
||||||
CopyLump<bspGridPoint_t, ibspGridPoint_t>( header, LUMP_LIGHTGRID, bspGridPoints );
|
CopyLump<bspGridPoint_t, ibspGridPoint_t>( header, LUMP_LIGHTGRID, bspGridPoints );
|
||||||
|
|
||||||
/* v47 extended lumps (17-18) */
|
/* BRX1 extension detection -- two-pass minimum probe */
|
||||||
if ( version == IBSP_VERSION_V47 ) {
|
bspGridPointsSH.clear();
|
||||||
/* advertisements */
|
{
|
||||||
CopyLump( header, LUMP_ADVERTISEMENTS, bspAds );
|
const int extStart = BSP_V46_HEADER_SIZE;
|
||||||
|
|
||||||
/* SH light grid */
|
/* pass 1: check no standard lump overlaps [extStart, extStart+8) */
|
||||||
const int length = header->lumps[LUMP_LIGHTGRID_SH].length;
|
bool canProbe = ( fileSize >= (size_t)extStart + 8 );
|
||||||
const int offset = header->lumps[LUMP_LIGHTGRID_SH].offset;
|
if ( canProbe ) {
|
||||||
if ( length > (int)sizeof( bspGridSHHeader_t ) ) {
|
for ( int i = 0; i < HEADER_LUMPS_V46; ++i ) {
|
||||||
const bspGridSHHeader_t *shHeader = (const bspGridSHHeader_t *)( data + offset );
|
const int lo = header->lumps[i].offset;
|
||||||
gridMinsSH = shHeader->gridMins;
|
const int llen = header->lumps[i].length;
|
||||||
gridSizeSH = shHeader->gridSize;
|
if ( llen > 0 && lo < extStart + 8 && lo + llen > extStart ) {
|
||||||
gridBoundsSH[0] = shHeader->gridBounds[0];
|
canProbe = false;
|
||||||
gridBoundsSH[1] = shHeader->gridBounds[1];
|
break;
|
||||||
gridBoundsSH[2] = shHeader->gridBounds[2];
|
}
|
||||||
const int numPoints = shHeader->numPoints;
|
}
|
||||||
const bspGridPointSH_t *points = (const bspGridPointSH_t *)( data + offset + sizeof( bspGridSHHeader_t ) );
|
|
||||||
bspGridPointsSH.assign( points, points + numPoints );
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
bspGridPointsSH.clear();
|
if ( canProbe ) {
|
||||||
|
const int magic = LittleLong( *(const int *)( data + extStart ) );
|
||||||
|
const int extCount = LittleLong( *(const int *)( data + extStart + 4 ) );
|
||||||
|
|
||||||
|
if ( magic == BSP_EXT_MAGIC_INT && extCount > 0 && extCount <= BSP_EXT_MAX_LUMPS ) {
|
||||||
|
const int extEnd = extStart + 8 + extCount * (int)sizeof( bspLump_t );
|
||||||
|
|
||||||
|
/* pass 2: verify full extension block range */
|
||||||
|
bool extValid = ( fileSize >= (size_t)extEnd );
|
||||||
|
if ( extValid ) {
|
||||||
|
for ( int i = 0; i < HEADER_LUMPS_V46; ++i ) {
|
||||||
|
const int lo = header->lumps[i].offset;
|
||||||
|
const int llen = header->lumps[i].length;
|
||||||
|
if ( llen > 0 && lo < extEnd && lo + llen > extStart ) {
|
||||||
|
extValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( extValid ) {
|
||||||
|
/* read extension lump directory */
|
||||||
|
const bspLump_t *extLumps = (const bspLump_t *)( data + extStart + 8 );
|
||||||
|
|
||||||
|
/* EXT_LUMP_LIGHTGRID_SH */
|
||||||
|
if ( extCount > EXT_LUMP_LIGHTGRID_SH ) {
|
||||||
|
const int off = LittleLong( extLumps[EXT_LUMP_LIGHTGRID_SH].offset );
|
||||||
|
const int len = LittleLong( extLumps[EXT_LUMP_LIGHTGRID_SH].length );
|
||||||
|
if ( len > (int)sizeof( bspGridSHHeader_t ) && off + len <= (int)fileSize ) {
|
||||||
|
const bspGridSHHeader_t *shHeader = (const bspGridSHHeader_t *)( data + off );
|
||||||
|
gridMinsSH = shHeader->gridMins;
|
||||||
|
gridSizeSH = shHeader->gridSize;
|
||||||
|
gridBoundsSH[0] = shHeader->gridBounds[0];
|
||||||
|
gridBoundsSH[1] = shHeader->gridBounds[1];
|
||||||
|
gridBoundsSH[2] = shHeader->gridBounds[2];
|
||||||
|
const int numPoints = shHeader->numPoints;
|
||||||
|
const bspGridPointSH_t *points = (const bspGridPointSH_t *)( data + off + sizeof( bspGridSHHeader_t ) );
|
||||||
|
bspGridPointsSH.assign( points, points + numPoints );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EXT_LUMP_LIGHTMAP_INFO */
|
||||||
|
if ( extCount > EXT_LUMP_LIGHTMAP_INFO ) {
|
||||||
|
const int off = LittleLong( extLumps[EXT_LUMP_LIGHTMAP_INFO].offset );
|
||||||
|
const int len = LittleLong( extLumps[EXT_LUMP_LIGHTMAP_INFO].length );
|
||||||
|
if ( len >= (int)sizeof( bspLightmapInfo_t ) && off + len <= (int)fileSize ) {
|
||||||
|
const bspLightmapInfo_t *lmInfo = (const bspLightmapInfo_t *)( data + off );
|
||||||
|
bspLightmapPageW = LittleLong( lmInfo->pageWidth );
|
||||||
|
bspLightmapPageH = LittleLong( lmInfo->pageHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sys_FPrintf( SYS_VRB, "BRX1 extension: %d lumps\n", extCount );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
bspAds.clear();
|
|
||||||
bspGridPointsSH.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -327,16 +346,12 @@ void LoadIBSPorRBSPFilePartially( const char *filename ){
|
||||||
if ( !force && memcmp( data, g_game->bspIdent, 4 ) ) {
|
if ( !force && memcmp( data, g_game->bspIdent, 4 ) ) {
|
||||||
Error( "%s is not a %s file", filename, g_game->bspIdent );
|
Error( "%s is not a %s file", filename, g_game->bspIdent );
|
||||||
}
|
}
|
||||||
if ( !force && version != IBSP_VERSION_V46 && version != IBSP_VERSION_V47 ) {
|
if ( !force && version != IBSP_VERSION_V46 ) {
|
||||||
Error( "%s is version %d, expected %d or %d", filename, version, IBSP_VERSION_V46, IBSP_VERSION_V47 );
|
Error( "%s is version %d, expected %d", filename, version, IBSP_VERSION_V46 );
|
||||||
}
|
}
|
||||||
|
|
||||||
const int numLumps = ( version == IBSP_VERSION_V47 ) ? HEADER_LUMPS_V47 : HEADER_LUMPS_V46;
|
|
||||||
|
|
||||||
bspHeader_t *header = (bspHeader_t *)file.data();
|
bspHeader_t *header = (bspHeader_t *)file.data();
|
||||||
SwapBlock( (int *)( (byte *)header + 8 ), numLumps * sizeof( bspLump_t ) );
|
SwapBlock( (int *)( (byte *)header + 8 ), HEADER_LUMPS_V46 * sizeof( bspLump_t ) );
|
||||||
for ( int i = numLumps; i < 100; ++i )
|
|
||||||
header->lumps[i] = {};
|
|
||||||
|
|
||||||
/* load/convert lumps */
|
/* load/convert lumps */
|
||||||
CopyLump( header, LUMP_SHADERS, bspShaders );
|
CopyLump( header, LUMP_SHADERS, bspShaders );
|
||||||
|
|
@ -355,23 +370,33 @@ void LoadIBSPorRBSPFilePartially( const char *filename ){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void WriteIBSPFile( const char *filename ){
|
void WriteIBSPFile( const char *filename ){
|
||||||
/* determine version: v47 if SH data exists, v46 otherwise */
|
/* always write v46 -- extensions go in BRX1 block after the header */
|
||||||
const bool extendedBSP = !bspGridPointsSH.empty();
|
const bool hasSHGrid = !bspGridPointsSH.empty();
|
||||||
const int bspVersion = extendedBSP ? IBSP_VERSION_V47 : IBSP_VERSION_V46;
|
const bool hasLmInfo = ( bspLightmapPageW != LIGHTMAP_WIDTH || bspLightmapPageH != LIGHTMAP_HEIGHT );
|
||||||
const int numLumps = extendedBSP ? HEADER_LUMPS_V47 : HEADER_LUMPS_V46;
|
const bool hasExtension = hasSHGrid || hasLmInfo;
|
||||||
const int headerSize = 8 + numLumps * (int)sizeof( bspLump_t );
|
|
||||||
|
|
||||||
ibspHeader_t header{};
|
ibspHeader_t header{};
|
||||||
|
|
||||||
//% Swapfile();
|
/* set up header -- always v46 */
|
||||||
|
|
||||||
/* set up header */
|
|
||||||
memcpy( header.ident, g_game->bspIdent, 4 );
|
memcpy( header.ident, g_game->bspIdent, 4 );
|
||||||
header.version = LittleLong( bspVersion );
|
header.version = LittleLong( IBSP_VERSION_V46 );
|
||||||
|
|
||||||
/* write initial header (placeholder, overwritten at the end) */
|
const int v46HeaderSize = (int)sizeof( ibspHeader_v46_t );
|
||||||
|
|
||||||
|
/* compute extension block size */
|
||||||
|
int extBlockSize = 0;
|
||||||
|
if ( hasExtension ) {
|
||||||
|
extBlockSize = 8 + EXT_LUMP_COUNT * (int)sizeof( bspLump_t ); /* magic + count + directory */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write initial header + extension placeholder (overwritten at the end) */
|
||||||
FILE *file = SafeOpenWrite( filename );
|
FILE *file = SafeOpenWrite( filename );
|
||||||
SafeWrite( file, &header, headerSize );
|
SafeWrite( file, &header, v46HeaderSize );
|
||||||
|
if ( hasExtension ) {
|
||||||
|
/* placeholder for extension block -- filled in at the end */
|
||||||
|
std::vector<byte> extPlaceholder( extBlockSize, 0 );
|
||||||
|
SafeWrite( file, extPlaceholder.data(), extBlockSize );
|
||||||
|
}
|
||||||
|
|
||||||
{ /* add marker lump */
|
{ /* add marker lump */
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
@ -381,7 +406,7 @@ void WriteIBSPFile( const char *filename ){
|
||||||
AddLump( file, header.lumps[0], std::vector<char>( marker.cbegin(), marker.cend() + 1 ) );
|
AddLump( file, header.lumps[0], std::vector<char>( marker.cbegin(), marker.cend() + 1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add standard lumps (0-16) */
|
/* add standard lumps (0-16) -- data starts after header + extension block */
|
||||||
AddLump( file, header.lumps[LUMP_SHADERS], bspShaders );
|
AddLump( file, header.lumps[LUMP_SHADERS], bspShaders );
|
||||||
AddLump( file, header.lumps[LUMP_PLANES], bspPlanes );
|
AddLump( file, header.lumps[LUMP_PLANES], bspPlanes );
|
||||||
AddLump( file, header.lumps[LUMP_LEAFS], bspLeafs );
|
AddLump( file, header.lumps[LUMP_LEAFS], bspLeafs );
|
||||||
|
|
@ -400,34 +425,52 @@ void WriteIBSPFile( const char *filename ){
|
||||||
AddLump( file, header.lumps[LUMP_FOGS], bspFogs );
|
AddLump( file, header.lumps[LUMP_FOGS], bspFogs );
|
||||||
AddLump( file, header.lumps[LUMP_DRAWINDEXES], bspDrawIndexes );
|
AddLump( file, header.lumps[LUMP_DRAWINDEXES], bspDrawIndexes );
|
||||||
|
|
||||||
/* v47 extended lumps (17-18) */
|
/* BRX1 extension lumps -- data appended after standard lumps */
|
||||||
if ( extendedBSP ) {
|
bspLump_t extLumps[EXT_LUMP_COUNT] = {};
|
||||||
/* advertisements */
|
if ( hasExtension ) {
|
||||||
AddLump( file, header.lumps[LUMP_ADVERTISEMENTS], bspAds );
|
/* SH light grid */
|
||||||
|
if ( hasSHGrid ) {
|
||||||
|
const size_t shHeaderSz = sizeof( bspGridSHHeader_t );
|
||||||
|
const size_t dataSz = bspGridPointsSH.size() * sizeof( bspGridPointSH_t );
|
||||||
|
std::vector<byte> shLump( shHeaderSz + dataSz );
|
||||||
|
bspGridSHHeader_t shHeader;
|
||||||
|
shHeader.gridMins = gridMinsSH;
|
||||||
|
shHeader.gridSize = gridSizeSH;
|
||||||
|
shHeader.gridBounds[0] = gridBoundsSH[0];
|
||||||
|
shHeader.gridBounds[1] = gridBoundsSH[1];
|
||||||
|
shHeader.gridBounds[2] = gridBoundsSH[2];
|
||||||
|
shHeader.numPoints = (int)bspGridPointsSH.size();
|
||||||
|
memcpy( shLump.data(), &shHeader, shHeaderSz );
|
||||||
|
memcpy( shLump.data() + shHeaderSz, bspGridPointsSH.data(), dataSz );
|
||||||
|
AddLump( file, extLumps[EXT_LUMP_LIGHTGRID_SH], shLump );
|
||||||
|
}
|
||||||
|
|
||||||
/* SH light grid -- header + points packed into a byte lump */
|
/* lightmap info */
|
||||||
const size_t shHeaderSz = sizeof( bspGridSHHeader_t );
|
if ( hasLmInfo ) {
|
||||||
const size_t dataSz = bspGridPointsSH.size() * sizeof( bspGridPointSH_t );
|
bspLightmapInfo_t lmInfo;
|
||||||
std::vector<byte> shLump( shHeaderSz + dataSz );
|
lmInfo.pageWidth = bspLightmapPageW;
|
||||||
bspGridSHHeader_t shHeader;
|
lmInfo.pageHeight = bspLightmapPageH;
|
||||||
shHeader.gridMins = gridMinsSH;
|
AddLump( file, extLumps[EXT_LUMP_LIGHTMAP_INFO], std::vector<bspLightmapInfo_t>( 1, lmInfo ) );
|
||||||
shHeader.gridSize = gridSizeSH;
|
}
|
||||||
shHeader.gridBounds[0] = gridBoundsSH[0];
|
|
||||||
shHeader.gridBounds[1] = gridBoundsSH[1];
|
|
||||||
shHeader.gridBounds[2] = gridBoundsSH[2];
|
|
||||||
shHeader.numPoints = (int)bspGridPointsSH.size();
|
|
||||||
memcpy( shLump.data(), &shHeader, shHeaderSz );
|
|
||||||
memcpy( shLump.data() + shHeaderSz, bspGridPointsSH.data(), dataSz );
|
|
||||||
AddLump( file, header.lumps[LUMP_LIGHTGRID_SH], shLump );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* emit bsp size */
|
/* emit bsp size */
|
||||||
const int size = ftell( file );
|
const int size = ftell( file );
|
||||||
Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / ( 1024 * 1024 ), size );
|
Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / ( 1024 * 1024 ), size );
|
||||||
|
|
||||||
/* write the completed header */
|
/* write the completed v46 header */
|
||||||
fseek( file, 0, SEEK_SET );
|
fseek( file, 0, SEEK_SET );
|
||||||
SafeWrite( file, &header, headerSize );
|
SafeWrite( file, &header, v46HeaderSize );
|
||||||
|
|
||||||
|
/* write the completed BRX1 extension block */
|
||||||
|
if ( hasExtension ) {
|
||||||
|
const int extMagic = LittleLong( BSP_EXT_MAGIC_INT );
|
||||||
|
const int extCount = LittleLong( EXT_LUMP_COUNT );
|
||||||
|
SafeWrite( file, &extMagic, 4 );
|
||||||
|
SafeWrite( file, &extCount, 4 );
|
||||||
|
SafeWrite( file, extLumps, EXT_LUMP_COUNT * sizeof( bspLump_t ) );
|
||||||
|
Sys_FPrintf( SYS_VRB, "BRX1 extension: %d lumps written\n", EXT_LUMP_COUNT );
|
||||||
|
}
|
||||||
|
|
||||||
/* close the file */
|
/* close the file */
|
||||||
fclose( file );
|
fclose( file );
|
||||||
|
|
|
||||||
|
|
@ -2722,12 +2722,18 @@ int LightMain( Args& args ){
|
||||||
}
|
}
|
||||||
Sys_Printf( "Default lightmap size set to %d x %d pixels\n", lmCustomSizeW, lmCustomSizeH );
|
Sys_Printf( "Default lightmap size set to %d x %d pixels\n", lmCustomSizeW, lmCustomSizeH );
|
||||||
|
|
||||||
/* enable external lightmaps */
|
/* handle non-default lightmap size */
|
||||||
if ( lmCustomSizeW != g_game->lightmapSize || lmCustomSizeH != g_game->lightmapSize ) {
|
if ( lmCustomSizeW != g_game->lightmapSize || lmCustomSizeH != g_game->lightmapSize ) {
|
||||||
/* -lightmapsize might just require -external for native external lms, but it has already been used in existing batches alone,
|
if ( extlmhack ) {
|
||||||
so brand new switch here for external lms, referenced by shaders hack/behavior */
|
/* -extlmhacksize: external TGA + custom shader hack (legacy, for vanilla Q3 engines) */
|
||||||
externalLightmaps = !extlmhack;
|
Sys_Printf( "External lightmap hack enabled\n" );
|
||||||
Sys_Printf( "Storing all lightmaps externally\n" );
|
}
|
||||||
|
else {
|
||||||
|
/* -lightmapsize: store natively in BSP via BRX1 extension */
|
||||||
|
bspLightmapPageW = lmCustomSizeW;
|
||||||
|
bspLightmapPageH = lmCustomSizeH;
|
||||||
|
Sys_Printf( "Lightmap pages stored in BSP at %d x %d (BRX1 extension)\n", bspLightmapPageW, bspLightmapPageH );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1741,7 +1741,9 @@ static void SetupOutLightmap( rawLightmap_t *lm, outLightmap_t *olm ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is this a "normal" bsp-stored lightmap? */
|
/* is this a "normal" bsp-stored lightmap? */
|
||||||
if ( ( lm->customWidth == g_game->lightmapSize && lm->customHeight == g_game->lightmapSize ) || externalLightmaps ) {
|
if ( ( lm->customWidth == g_game->lightmapSize && lm->customHeight == g_game->lightmapSize )
|
||||||
|
|| ( lm->customWidth == bspLightmapPageW && lm->customHeight == bspLightmapPageH )
|
||||||
|
|| externalLightmaps ) {
|
||||||
olm->lightmapNum = numBSPLightmaps;
|
olm->lightmapNum = numBSPLightmaps;
|
||||||
numBSPLightmaps++;
|
numBSPLightmaps++;
|
||||||
|
|
||||||
|
|
@ -2887,7 +2889,7 @@ void StoreSurfaceLightmaps( bool fastAllocate, bool storeForReal ){
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
/* count the bsp lightmaps and allocate space */
|
/* count the bsp lightmaps and allocate space */
|
||||||
const size_t gameLmSize = g_game->lightmapSize * g_game->lightmapSize * sizeof( Vector3b );
|
const size_t gameLmSize = (size_t)lmCustomSizeW * lmCustomSizeH * sizeof( Vector3b );
|
||||||
if ( numBSPLightmaps == 0 || externalLightmaps ) {
|
if ( numBSPLightmaps == 0 || externalLightmaps ) {
|
||||||
bspLightBytes.clear();
|
bspLightBytes.clear();
|
||||||
}
|
}
|
||||||
|
|
@ -3221,8 +3223,10 @@ void StoreSurfaceLightmaps( bool fastAllocate, bool storeForReal ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* devise a custom shader for this surface (fixme: make this work with light styles) */
|
/* devise a custom shader for this surface (fixme: make this work with light styles) */
|
||||||
|
/* skip this hack when using BRX1 native lightmap pages */
|
||||||
else if ( olm != nullptr && lm != nullptr && !externalLightmaps &&
|
else if ( olm != nullptr && lm != nullptr && !externalLightmaps &&
|
||||||
( olm->customWidth != g_game->lightmapSize || olm->customHeight != g_game->lightmapSize ) ) {
|
( olm->customWidth != g_game->lightmapSize || olm->customHeight != g_game->lightmapSize ) &&
|
||||||
|
( olm->customWidth != bspLightmapPageW || olm->customHeight != bspLightmapPageH ) ) {
|
||||||
/* get output lightmap */
|
/* get output lightmap */
|
||||||
olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ];
|
olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,27 @@ struct bspGridPoint_t
|
||||||
byte latLong[ 2 ];
|
byte latLong[ 2 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SH light grid header -- stored at the start of LUMP_LIGHTGRID_SH */
|
/* BRX1 backward-compatible BSP extension format.
|
||||||
|
Extension block sits at offset 144 (right after v46 header).
|
||||||
|
Layout: magic(4) + count(4) + lump_dir(count*8) */
|
||||||
|
#define BSP_EXT_MAGIC "BRX1"
|
||||||
|
#define BSP_EXT_MAGIC_INT (('1'<<24)+('X'<<16)+('R'<<8)+'B') /* little-endian "BRX1" */
|
||||||
|
#define BSP_V46_HEADER_SIZE 144
|
||||||
|
#define BSP_EXT_MAX_LUMPS 32
|
||||||
|
|
||||||
|
/* Extension lump indices */
|
||||||
|
#define EXT_LUMP_LIGHTGRID_SH 0
|
||||||
|
#define EXT_LUMP_LIGHTMAP_INFO 1
|
||||||
|
#define EXT_LUMP_COUNT 2 /* total extension lumps we use */
|
||||||
|
|
||||||
|
/* Lightmap page size metadata -- stored in EXT_LUMP_LIGHTMAP_INFO */
|
||||||
|
struct bspLightmapInfo_t
|
||||||
|
{
|
||||||
|
int pageWidth;
|
||||||
|
int pageHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SH light grid header -- stored at the start of EXT_LUMP_LIGHTGRID_SH */
|
||||||
struct bspGridSHHeader_t
|
struct bspGridSHHeader_t
|
||||||
{
|
{
|
||||||
Vector3 gridMins; /* world-space origin of the SH grid */
|
Vector3 gridMins; /* world-space origin of the SH grid */
|
||||||
|
|
@ -2166,6 +2186,8 @@ inline bool exportLightmaps;
|
||||||
inline bool externalLightmaps;
|
inline bool externalLightmaps;
|
||||||
inline int lmCustomSizeW = LIGHTMAP_WIDTH;
|
inline int lmCustomSizeW = LIGHTMAP_WIDTH;
|
||||||
inline int lmCustomSizeH = LIGHTMAP_WIDTH;
|
inline int lmCustomSizeH = LIGHTMAP_WIDTH;
|
||||||
|
inline int bspLightmapPageW = LIGHTMAP_WIDTH; /* actual page size written to BSP (for BRX1 extension) */
|
||||||
|
inline int bspLightmapPageH = LIGHTMAP_HEIGHT;
|
||||||
inline const char * lmCustomDir;
|
inline const char * lmCustomDir;
|
||||||
inline int lmLimitSize;
|
inline int lmLimitSize;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue