diff --git a/tools/quake3/common/imagelib.c b/tools/quake3/common/imagelib.c index b6fba38d..bb422ec9 100644 --- a/tools/quake3/common/imagelib.c +++ b/tools/quake3/common/imagelib.c @@ -1169,6 +1169,26 @@ void WriteTGA( const char *filename, byte *data, int width, int height ) { free( buffer ); } +void WriteTGAGray( const char *filename, byte *data, int width, int height ) { + byte buffer[18]; + int i; + int c; + FILE *f; + + memset( buffer, 0, 18 ); + buffer[2] = 3; // uncompressed type + buffer[12] = width & 255; + buffer[13] = width >> 8; + buffer[14] = height & 255; + buffer[15] = height >> 8; + buffer[16] = 8; // pixel size + + f = fopen( filename, "wb" ); + fwrite( buffer, 1, 18, f ); + fwrite( data, 1, width * height, f ); + fclose( f ); +} + /* ============================================================================ diff --git a/tools/quake3/common/imagelib.h b/tools/quake3/common/imagelib.h index 37277170..2e6a6a98 100644 --- a/tools/quake3/common/imagelib.h +++ b/tools/quake3/common/imagelib.h @@ -39,6 +39,7 @@ void Save256Image( const char *name, byte *pixels, byte *palette, void LoadTGA( const char *filename, byte **pixels, int *width, int *height ); void LoadTGABuffer( const byte *buffer, const byte* enddata, byte **pic, int *width, int *height ); void WriteTGA( const char *filename, byte *data, int width, int height ); +void WriteTGAGray (const char *filename, byte *data, int width, int height); int LoadJPGBuff( void *src_buffer, int src_size, unsigned char **pic, int *width, int *height ); void Load32BitImage( const char *name, unsigned **pixels, int *width, int *height ); diff --git a/tools/quake3/q3map2/bsp.c b/tools/quake3/q3map2/bsp.c index eb615e61..929aa93c 100644 --- a/tools/quake3/q3map2/bsp.c +++ b/tools/quake3/q3map2/bsp.c @@ -44,7 +44,6 @@ ------------------------------------------------------------------------------- */ - /* ProcessAdvertisements() copies advertisement info into the BSP structures @@ -842,11 +841,21 @@ int BSPMain( int argc, char **argv ){ Sys_Printf( "Debug portal surfaces enabled\n" ); debugPortals = qtrue; } - else if ( !strcmp( argv[ i ], "-bsp" ) ) { - Sys_Printf( "-bsp argument unnecessary\n" ); + else if ( !strcmp( argv[ i ], "-altsplit" ) ) + { + Sys_Printf( "Alternate BSP splitting (by 27) enabled\n" ); + bspAlternateSplitWeights = qtrue; } - else{ - Sys_FPrintf( SYS_WRN, "WARNING: Unknown option \"%s\"\n", argv[ i ] ); + else if ( !strcmp( argv[ i ], "-deep" ) ) + { + Sys_Printf( "Deep BSP tree generation enabled\n" ); + deepBSP = qtrue; + } + else if( !strcmp( argv[ i ], "-bsp" ) ) + Sys_Printf( "-bsp argument unnecessary\n" ); + else + { + Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] ); } } diff --git a/tools/quake3/q3map2/facebsp.c b/tools/quake3/q3map2/facebsp.c index 66a009c2..888a44ad 100644 --- a/tools/quake3/q3map2/facebsp.c +++ b/tools/quake3/q3map2/facebsp.c @@ -88,8 +88,8 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, vec3_t normal; float dist; int planenum; - - + float sizeBias; + /* ydnar: set some defaults */ *splitPlaneNum = -1; /* leaf */ *compileFlags = 0; @@ -117,14 +117,14 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, bestValue = -99999; bestSplit = list; - for ( split = list; split; split = split->next ) - split->checked = qfalse; + // div0: this check causes detail/structural mixes + //for( split = list; split; split = split->next ) + // split->checked = qfalse; for ( split = list; split; split = split->next ) { - if ( split->checked ) { - continue; - } + //if ( split->checked ) + // continue; plane = &mapplanes[ split->planenum ]; splits = 0; @@ -134,7 +134,7 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, for ( check = list ; check ; check = check->next ) { if ( check->planenum == split->planenum ) { facing++; - check->checked = qtrue; // won't need to test this plane again + //check->checked = qtrue; // won't need to test this plane again continue; } side = WindingOnPlaneSide( check->w, plane->normal, plane->dist ); @@ -148,11 +148,30 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, back++; } } - value = 5 * facing - 5 * splits; // - abs(front-back); - if ( plane->type < 3 ) { - value += 5; // axial is better + + if(bspAlternateSplitWeights) + { + // from 27 + + //Bigger is better + sizeBias=WindingArea(split->w); + + //Base score = 20000 perfectly balanced + value = 20000-(abs(front-back)); + value -= plane->counter;// If we've already used this plane sometime in the past try not to use it again + value -= facing ; // if we're going to have alot of other surfs use this plane, we want to get it in quickly. + value -= splits*5; //more splits = bad + value += sizeBias*10; //We want a huge score bias based on plane size } - value += split->priority; // prioritize hints higher + else + { + value = 5*facing - 5*splits; // - abs(front-back); + if ( plane->type < 3 ) { + value+=5; // axial is better + } + } + + value += split->priority; // prioritize hints higher if ( value > bestValue ) { bestValue = value; @@ -168,6 +187,8 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, /* set best split data */ *splitPlaneNum = bestSplit->planenum; *compileFlags = bestSplit->compileFlags; + + if (*splitPlaneNum>-1) mapplanes[ *splitPlaneNum ].counter++; } @@ -215,6 +236,7 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ /* if we don't have any more faces, this is a node */ if ( splitPlaneNum == -1 ) { node->planenum = PLANENUM_LEAF; + node->has_structural_children = qfalse; c_faceLeafs++; return; } @@ -222,9 +244,12 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ /* partition the list */ node->planenum = splitPlaneNum; node->compileFlags = compileFlags; + node->has_structural_children = !(compileFlags & C_DETAIL) && !node->opaque; plane = &mapplanes[ splitPlaneNum ]; childLists[0] = NULL; childLists[1] = NULL; + + qboolean isstruct = 0; for ( split = list; split; split = next ) { /* set next */ @@ -236,6 +261,9 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ continue; } + if(!(split->compileFlags & C_DETAIL)) + isstruct = 1; + /* determine which side the face falls on */ side = WindingOnPlaneSide( split->w, plane->normal, plane->dist ); @@ -292,6 +320,7 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ for ( i = 0 ; i < 2 ; i++ ) { BuildFaceTree_r( node->children[i], childLists[i] ); + node->has_structural_children |= node->children[i]->has_structural_children; } } @@ -324,6 +353,11 @@ tree_t *FaceBSP( face_t *list ) { } Sys_FPrintf( SYS_VRB, "%9d faces\n", count ); + for ( i = 0; i < nummapplanes; i++ ) + { + mapplanes[ i ].counter = 0; + } + tree->headnode = AllocNode(); VectorCopy( tree->mins, tree->headnode->mins ); VectorCopy( tree->maxs, tree->headnode->maxs ); @@ -354,7 +388,7 @@ face_t *MakeStructuralBSPFaceList( brush_t *list ){ flist = NULL; for ( b = list; b != NULL; b = b->next ) { - if ( b->detail ) { + if ( !deepBSP && b->detail ) { continue; } @@ -377,6 +411,9 @@ face_t *MakeStructuralBSPFaceList( brush_t *list ){ f->w = CopyWinding( w ); f->planenum = s->planenum & ~1; f->compileFlags = s->compileFlags; /* ydnar */ + if ( b->detail ) { + f->compileFlags |= C_DETAIL; + } /* ydnar: set priority */ f->priority = 0; @@ -389,6 +426,9 @@ face_t *MakeStructuralBSPFaceList( brush_t *list ){ if ( f->compileFlags & C_AREAPORTAL ) { f->priority += AREAPORTAL_PRIORITY; } + if ( f->compileFlags & C_DETAIL ) { + f->priority += DETAIL_PRIORITY; + } /* get next face */ f->next = flist; @@ -417,7 +457,7 @@ face_t *MakeVisibleBSPFaceList( brush_t *list ){ flist = NULL; for ( b = list; b != NULL; b = b->next ) { - if ( b->detail ) { + if ( !deepBSP && b->detail ) { continue; } @@ -440,6 +480,9 @@ face_t *MakeVisibleBSPFaceList( brush_t *list ){ f->w = CopyWinding( w ); f->planenum = s->planenum & ~1; f->compileFlags = s->compileFlags; /* ydnar */ + if ( b->detail ) { + f->compileFlags |= C_DETAIL; + } /* ydnar: set priority */ f->priority = 0; @@ -452,6 +495,9 @@ face_t *MakeVisibleBSPFaceList( brush_t *list ){ if ( f->compileFlags & C_AREAPORTAL ) { f->priority += AREAPORTAL_PRIORITY; } + if ( f->compileFlags & C_DETAIL ) { + f->priority += DETAIL_PRIORITY; + } /* get next face */ f->next = flist; diff --git a/tools/quake3/q3map2/fog.c b/tools/quake3/q3map2/fog.c index 1b23bad2..35e288ba 100644 --- a/tools/quake3/q3map2/fog.c +++ b/tools/quake3/q3map2/fog.c @@ -787,7 +787,7 @@ void CreateMapFogs( void ){ /* set up fog */ fog = &mapFogs[ numMapFogs++ ]; - fog->si = ShaderInfoForShader( globalFog ); + fog->si = ShaderInfoForShaderNull( globalFog ); if ( fog->si == NULL ) { Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog ); } diff --git a/tools/quake3/q3map2/game__null.h b/tools/quake3/q3map2/game__null.h index c291a50f..9191051b 100644 --- a/tools/quake3/q3map2/game__null.h +++ b/tools/quake3/q3map2/game__null.h @@ -64,6 +64,12 @@ 0, /* lightmap width/height */ 0, /* lightmap gamma */ 0, /* lightmap compensate */ + 0, /* minimap size */ + 0, /* minimap sharpener */ + 0, /* minimap border */ + qfalse, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + NULL, /* minimap name format */ NULL, /* bsp file prefix */ 0, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_ef.h b/tools/quake3/q3map2/game_ef.h index efce240d..0a8168a0 100644 --- a/tools/quake3/q3map2/game_ef.h +++ b/tools/quake3/q3map2/game_ef.h @@ -114,6 +114,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 46, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_etut.h b/tools/quake3/q3map2/game_etut.h index 9482dd54..1f0a8962 100644 --- a/tools/quake3/q3map2/game_etut.h +++ b/tools/quake3/q3map2/game_etut.h @@ -149,6 +149,12 @@ 128, /* lightmap width/height */ 2.2f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 47, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_ja.h b/tools/quake3/q3map2/game_ja.h index d9d4311d..f4778043 100644 --- a/tools/quake3/q3map2/game_ja.h +++ b/tools/quake3/q3map2/game_ja.h @@ -68,6 +68,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "RBSP", /* bsp file prefix */ 1, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_jk2.h b/tools/quake3/q3map2/game_jk2.h index a990339f..90351e0f 100644 --- a/tools/quake3/q3map2/game_jk2.h +++ b/tools/quake3/q3map2/game_jk2.h @@ -65,6 +65,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "RBSP", /* bsp file prefix */ 1, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_nexuiz.h b/tools/quake3/q3map2/game_nexuiz.h index a11cd2f3..f909c4bc 100644 --- a/tools/quake3/q3map2/game_nexuiz.h +++ b/tools/quake3/q3map2/game_nexuiz.h @@ -64,6 +64,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 1.0f / 66.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "../gfx/%s_mini.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 46, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_qfusion.h b/tools/quake3/q3map2/game_qfusion.h index b17f9fa8..9ddebdc1 100644 --- a/tools/quake3/q3map2/game_qfusion.h +++ b/tools/quake3/q3map2/game_qfusion.h @@ -113,6 +113,12 @@ 512, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 256, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_WHITE, /* minimap mode */ + "../minimaps/%s.tga", /* minimap name format */ "FBSP", /* bsp file prefix */ 1, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_quake3.h b/tools/quake3/q3map2/game_quake3.h index 2ffdc246..07a1c9a2 100644 --- a/tools/quake3/q3map2/game_quake3.h +++ b/tools/quake3/q3map2/game_quake3.h @@ -113,6 +113,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 46, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_quakelive.h b/tools/quake3/q3map2/game_quakelive.h index ad014252..78b1329d 100644 --- a/tools/quake3/q3map2/game_quakelive.h +++ b/tools/quake3/q3map2/game_quakelive.h @@ -77,6 +77,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 47, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_reaction.h b/tools/quake3/q3map2/game_reaction.h index 00016c3f..970ccd25 100644 --- a/tools/quake3/q3map2/game_reaction.h +++ b/tools/quake3/q3map2/game_reaction.h @@ -85,6 +85,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 46, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_sof2.h b/tools/quake3/q3map2/game_sof2.h index 4c957714..91b26df4 100644 --- a/tools/quake3/q3map2/game_sof2.h +++ b/tools/quake3/q3map2/game_sof2.h @@ -140,6 +140,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "RBSP", /* bsp file prefix */ 1, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_tenebrae.h b/tools/quake3/q3map2/game_tenebrae.h index c76d45de..57e45eca 100644 --- a/tools/quake3/q3map2/game_tenebrae.h +++ b/tools/quake3/q3map2/game_tenebrae.h @@ -113,6 +113,12 @@ 512, /* lightmap width/height */ 2.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 46, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_tremulous.h b/tools/quake3/q3map2/game_tremulous.h index 87601baa..0f6d050f 100644 --- a/tools/quake3/q3map2/game_tremulous.h +++ b/tools/quake3/q3map2/game_tremulous.h @@ -71,6 +71,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 46, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_unvanquished.h b/tools/quake3/q3map2/game_unvanquished.h index 1c85c300..e56d7347 100644 --- a/tools/quake3/q3map2/game_unvanquished.h +++ b/tools/quake3/q3map2/game_unvanquished.h @@ -41,6 +41,7 @@ several games based on the Quake III Arena engine, in the form of "Q3Map2." content and surface flags - also uses defines from game_quake3.h ------------------------------------------------------------------------------- */ + #define UNV_CONT_NOALIENBUILD 0x1000 #define UNV_CONT_NOHUMANBUILD 0x2000 #define UNV_CONT_NOBUILD 0x4000 @@ -72,6 +73,12 @@ game_t struct 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_WHITE, /* minimap mode */ + "../minimaps/%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 46, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ @@ -84,13 +91,11 @@ game_t struct /* default */ { "default", Q_CONT_SOLID, -1, 0, -1, C_SOLID, -1 }, - /* ydnar */ { "lightgrid", 0, 0, 0, 0, C_LIGHTGRID, 0 }, { "antiportal", 0, 0, 0, 0, C_ANTIPORTAL, 0 }, { "skip", 0, 0, 0, 0, C_SKIP, 0 }, - /* compiler */ { "origin", Q_CONT_ORIGIN, Q_CONT_SOLID, 0, 0, C_ORIGIN | C_TRANSLUCENT, C_SOLID }, { "areaportal", Q_CONT_AREAPORTAL, Q_CONT_SOLID, 0, 0, C_AREAPORTAL | C_TRANSLUCENT, C_SOLID }, @@ -105,7 +110,6 @@ game_t struct { "nolightmap", 0, 0, Q_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 }, { "pointlight", 0, 0, Q_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 }, - /* game */ { "nonsolid", 0, Q_CONT_SOLID, Q_SURF_NONSOLID, 0, 0, C_SOLID }, @@ -138,7 +142,6 @@ game_t struct { "nodlight", 0, 0, Q_SURF_NODLIGHT, 0, 0, 0 }, { "dust", 0, 0, Q_SURF_DUST, 0, 0, 0 }, - /* unvanquished */ {"noalienbuild", UNV_CONT_NOALIENBUILD, 0, 0, 0, 0, 0 }, {"nohumanbuild", UNV_CONT_NOHUMANBUILD, 0, 0, 0, 0, 0 }, @@ -148,13 +151,10 @@ game_t struct {"nohumanbuildsurface", 0, 0, UNV_SURF_NOHUMANBUILDSURFACE, 0, 0, 0 }, {"nobuildsurface", 0, 0, UNV_SURF_NOBUILDSURFACE, 0, 0, 0 }, - /* null */ { NULL, 0, 0, 0, 0, 0, 0 } } } - - /* end marker */ #endif diff --git a/tools/quake3/q3map2/game_wolf.h b/tools/quake3/q3map2/game_wolf.h index 5d600612..6fed3761 100644 --- a/tools/quake3/q3map2/game_wolf.h +++ b/tools/quake3/q3map2/game_wolf.h @@ -130,6 +130,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 47, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/game_wolfet.h b/tools/quake3/q3map2/game_wolfet.h index fbcb6966..57151e29 100644 --- a/tools/quake3/q3map2/game_wolfet.h +++ b/tools/quake3/q3map2/game_wolfet.h @@ -67,6 +67,12 @@ 128, /* lightmap width/height */ 1.0f, /* lightmap gamma */ 1.0f, /* lightmap compensate */ + 512, /* minimap size */ + 1.0f, /* minimap sharpener */ + 0.0f, /* minimap border */ + qtrue, /* minimap keep aspect */ + MINIMAP_MODE_GRAY, /* minimap mode */ + "%s.tga", /* minimap name format */ "IBSP", /* bsp file prefix */ 47, /* bsp file version */ qfalse, /* cod-style lump len/ofs order */ diff --git a/tools/quake3/q3map2/light_trace.c b/tools/quake3/q3map2/light_trace.c index cc27fcc3..5fe77d07 100644 --- a/tools/quake3/q3map2/light_trace.c +++ b/tools/quake3/q3map2/light_trace.c @@ -1094,7 +1094,7 @@ static void PopulateWithPicoModel( int castShadows, picoModel_t *model, m4x4_t t if ( shader == NULL ) { continue; } - ti.si = ShaderInfoForShader( PicoGetShaderName( shader ) ); + ti.si = ShaderInfoForShaderNull( PicoGetShaderName( shader ) ); if ( ti.si == NULL ) { continue; } diff --git a/tools/quake3/q3map2/light_ydnar.c b/tools/quake3/q3map2/light_ydnar.c index 117167c2..38690791 100644 --- a/tools/quake3/q3map2/light_ydnar.c +++ b/tools/quake3/q3map2/light_ydnar.c @@ -1596,8 +1596,9 @@ void DirtyRawLightmap( int rawLightmapNum ){ static qboolean SubmapRawLuxel( rawLightmap_t *lm, int x, int y, float bx, float by, int *sampleCluster, vec3_t sampleOrigin, vec3_t sampleNormal ){ int i, *cluster, *cluster2; - float *origin, *origin2, *normal; - vec3_t originVecs[ 2 ]; + float *origin, *origin2, *normal; //% , *normal2; + vec3_t originVecs[ 2 ]; //% , normalVecs[ 2 ]; + /* calulate x vector */ if ( ( x < ( lm->sw - 1 ) && bx >= 0.0f ) || ( x == 0 && bx <= 0.0f ) ) { @@ -1612,7 +1613,7 @@ static qboolean SubmapRawLuxel( rawLightmap_t *lm, int x, int y, float bx, float cluster2 = SUPER_CLUSTER( x, y ); origin2 = SUPER_ORIGIN( x, y ); } - else{ + else { Sys_FPrintf( SYS_WRN, "WARNING: Spurious lightmap S vector\n" ); VectorClear( originVecs[0] ); origin = originVecs[0]; @@ -1634,7 +1635,7 @@ static qboolean SubmapRawLuxel( rawLightmap_t *lm, int x, int y, float bx, float cluster2 = SUPER_CLUSTER( x, y ); origin2 = SUPER_ORIGIN( x, y ); } - else{ + else { Sys_FPrintf( SYS_WRN, "WARNING: Spurious lightmap T vector\n" ); VectorClear( originVecs[1] ); origin = originVecs[1]; @@ -2774,15 +2775,16 @@ void IlluminateVertexes( int num ){ determines opaque brushes in the world and find sky shaders for sunlight calculations */ -void SetupBrushes( void ){ - int i, j, b, compileFlags; +void SetupBrushesFlags( unsigned int mask_any, unsigned int test_any, unsigned int mask_all, unsigned int test_all ) +{ + int i, j, b; + unsigned int compileFlags, allCompileFlags; qboolean inside; bspBrush_t *brush; bspBrushSide_t *side; bspShader_t *shader; shaderInfo_t *si; - /* note it */ Sys_FPrintf( SYS_VRB, "--- SetupBrushes ---\n" ); @@ -2805,6 +2807,7 @@ void SetupBrushes( void ){ /* check all sides */ inside = qtrue; compileFlags = 0; + allCompileFlags = ~( 0u ); for ( j = 0; j < brush->numSides && inside; j++ ) { /* do bsp shader calculations */ @@ -2812,17 +2815,18 @@ void SetupBrushes( void ){ shader = &bspShaders[ side->shaderNum ]; /* get shader info */ - si = ShaderInfoForShader( shader->shader ); + si = ShaderInfoForShaderNull( shader->shader ); if ( si == NULL ) { continue; } /* or together compile flags */ compileFlags |= si->compileFlags; + allCompileFlags &= si->compileFlags; } /* determine if this brush is opaque to light */ - if ( !( compileFlags & C_TRANSLUCENT ) ) { + if ( ( compileFlags & mask_any ) == test_any && ( allCompileFlags & mask_all ) == test_all ) { opaqueBrushes[ b >> 3 ] |= ( 1 << ( b & 7 ) ); numOpaqueBrushes++; maxOpaqueBrush = i; @@ -2832,6 +2836,9 @@ void SetupBrushes( void ){ /* emit some statistics */ Sys_FPrintf( SYS_VRB, "%9d opaque brushes\n", numOpaqueBrushes ); } +void SetupBrushes( void ){ + SetupBrushesFlags( C_TRANSLUCENT, 0, 0, 0 ); +} diff --git a/tools/quake3/q3map2/lightmaps_ydnar.c b/tools/quake3/q3map2/lightmaps_ydnar.c index e8114380..b3ac49ba 100644 --- a/tools/quake3/q3map2/lightmaps_ydnar.c +++ b/tools/quake3/q3map2/lightmaps_ydnar.c @@ -865,6 +865,14 @@ static int CompareSurfaceInfo( const void *a, const void *b ){ return -1; } + /* 27: then shader! */ + if ( aInfo->si < bInfo->si ) { + return 1; + } + else if ( aInfo->si > bInfo->si ) { + return -1; + } + /* then lightmap sample size */ if ( aInfo->sampleSize < bInfo->sampleSize ) { return 1; diff --git a/tools/quake3/q3map2/main.c b/tools/quake3/q3map2/main.c index 3a92b6f5..45d394fb 100644 --- a/tools/quake3/q3map2/main.c +++ b/tools/quake3/q3map2/main.c @@ -248,6 +248,11 @@ int main( int argc, char **argv ){ r = ConvertBSPMain( argc - 1, argv + 1 ); } + /* div0: minimap */ + else if ( !strcmp( argv[ 1 ], "-minimap" ) ) { + r = MiniMapBSPMain( argc - 1, argv + 1 ); + } + /* ydnar: otherwise create a bsp */ else{ r = BSPMain( argc, argv ); diff --git a/tools/quake3/q3map2/minimap.c b/tools/quake3/q3map2/minimap.c new file mode 100644 index 00000000..204e396c --- /dev/null +++ b/tools/quake3/q3map2/minimap.c @@ -0,0 +1,778 @@ +/* ------------------------------------------------------------------------------- + + Copyright (C) 1999-2007 id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. + + This file is part of GtkRadiant. + + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + ------------------------------------------------------------------------------- + + This code has been altered significantly from its original form, to support + several games based on the Quake III Arena engine, in the form of "Q3Map2." + + ------------------------------------------------------------------------------- */ + + + +/* dependencies */ +#include "q3map2.h" + +/* minimap stuff */ + +typedef struct minimap_s +{ + bspModel_t *model; + int width; + int height; + int samples; + float *sample_offsets; + float sharpen_boxmult; + float sharpen_centermult; + float boost, brightness, contrast; + float *data1f; + float *sharpendata1f; + vec3_t mins, size; +} +minimap_t; + +static minimap_t minimap; + +qboolean BrushIntersectionWithLine( bspBrush_t *brush, vec3_t start, vec3_t dir, float *t_in, float *t_out ){ + int i; + qboolean in = qfalse, out = qfalse; + bspBrushSide_t *sides = &bspBrushSides[brush->firstSide]; + + for ( i = 0; i < brush->numSides; ++i ) + { + bspPlane_t *p = &bspPlanes[sides[i].planeNum]; + float sn = DotProduct( start, p->normal ); + float dn = DotProduct( dir, p->normal ); + if ( dn == 0 ) { + if ( sn > p->dist ) { + return qfalse; // outside! + } + } + else + { + float t = ( p->dist - sn ) / dn; + if ( dn < 0 ) { + if ( !in || t > *t_in ) { + *t_in = t; + in = qtrue; + // as t_in can only increase, and t_out can only decrease, early out + if ( out && *t_in >= *t_out ) { + return qfalse; + } + } + } + else + { + if ( !out || t < *t_out ) { + *t_out = t; + out = qtrue; + // as t_in can only increase, and t_out can only decrease, early out + if ( in && *t_in >= *t_out ) { + return qfalse; + } + } + } + } + } + return in && out; +} + +static float MiniMapSample( float x, float y ){ + vec3_t org, dir; + int i, bi; + float t0, t1; + float samp; + bspBrush_t *b; + bspBrushSide_t *s; + int cnt; + + org[0] = x; + org[1] = y; + org[2] = 0; + dir[0] = 0; + dir[1] = 0; + dir[2] = 1; + + cnt = 0; + samp = 0; + for ( i = 0; i < minimap.model->numBSPBrushes; ++i ) + { + bi = minimap.model->firstBSPBrush + i; + if ( opaqueBrushes[bi >> 3] & ( 1 << ( bi & 7 ) ) ) { + b = &bspBrushes[bi]; + + // sort out mins/maxs of the brush + s = &bspBrushSides[b->firstSide]; + if ( x < -bspPlanes[s[0].planeNum].dist ) { + continue; + } + if ( x > +bspPlanes[s[1].planeNum].dist ) { + continue; + } + if ( y < -bspPlanes[s[2].planeNum].dist ) { + continue; + } + if ( y > +bspPlanes[s[3].planeNum].dist ) { + continue; + } + + if ( BrushIntersectionWithLine( b, org, dir, &t0, &t1 ) ) { + samp += t1 - t0; + ++cnt; + } + } + } + + return samp; +} + +void RandomVector2f( float v[2] ){ + do + { + v[0] = 2 * Random() - 1; + v[1] = 2 * Random() - 1; + } + while ( v[0] * v[0] + v[1] * v[1] > 1 ); +} + +static void MiniMapRandomlySupersampled( int y ){ + int x, i; + float *p = &minimap.data1f[y * minimap.width]; + float ymin = minimap.mins[1] + minimap.size[1] * ( y / (float) minimap.height ); + float dx = minimap.size[0] / (float) minimap.width; + float dy = minimap.size[1] / (float) minimap.height; + float uv[2]; + float thisval; + + for ( x = 0; x < minimap.width; ++x ) + { + float xmin = minimap.mins[0] + minimap.size[0] * ( x / (float) minimap.width ); + float val = 0; + + for ( i = 0; i < minimap.samples; ++i ) + { + RandomVector2f( uv ); + thisval = MiniMapSample( + xmin + ( uv[0] + 0.5 ) * dx, /* exaggerated random pattern for better results */ + ymin + ( uv[1] + 0.5 ) * dy /* exaggerated random pattern for better results */ + ); + val += thisval; + } + val /= minimap.samples * minimap.size[2]; + *p++ = val; + } +} + +static void MiniMapSupersampled( int y ){ + int x, i; + float *p = &minimap.data1f[y * minimap.width]; + float ymin = minimap.mins[1] + minimap.size[1] * ( y / (float) minimap.height ); + float dx = minimap.size[0] / (float) minimap.width; + float dy = minimap.size[1] / (float) minimap.height; + + for ( x = 0; x < minimap.width; ++x ) + { + float xmin = minimap.mins[0] + minimap.size[0] * ( x / (float) minimap.width ); + float val = 0; + + for ( i = 0; i < minimap.samples; ++i ) + { + float thisval = MiniMapSample( + xmin + minimap.sample_offsets[2 * i + 0] * dx, + ymin + minimap.sample_offsets[2 * i + 1] * dy + ); + val += thisval; + } + val /= minimap.samples * minimap.size[2]; + *p++ = val; + } +} + +static void MiniMapNoSupersampling( int y ){ + int x; + float *p = &minimap.data1f[y * minimap.width]; + float ymin = minimap.mins[1] + minimap.size[1] * ( ( y + 0.5 ) / (float) minimap.height ); + + for ( x = 0; x < minimap.width; ++x ) + { + float xmin = minimap.mins[0] + minimap.size[0] * ( ( x + 0.5 ) / (float) minimap.width ); + *p++ = MiniMapSample( xmin, ymin ) / minimap.size[2]; + } +} + +static void MiniMapSharpen( int y ){ + int x; + qboolean up = ( y > 0 ); + qboolean down = ( y < minimap.height - 1 ); + float *p = &minimap.data1f[y * minimap.width]; + float *q = &minimap.sharpendata1f[y * minimap.width]; + + for ( x = 0; x < minimap.width; ++x ) + { + qboolean left = ( x > 0 ); + qboolean right = ( x < minimap.width - 1 ); + float val = p[0] * minimap.sharpen_centermult; + + if ( left && up ) { + val += p[-1 - minimap.width] * minimap.sharpen_boxmult; + } + if ( left && down ) { + val += p[-1 + minimap.width] * minimap.sharpen_boxmult; + } + if ( right && up ) { + val += p[+1 - minimap.width] * minimap.sharpen_boxmult; + } + if ( right && down ) { + val += p[+1 + minimap.width] * minimap.sharpen_boxmult; + } + + if ( left ) { + val += p[-1] * minimap.sharpen_boxmult; + } + if ( right ) { + val += p[+1] * minimap.sharpen_boxmult; + } + if ( up ) { + val += p[-minimap.width] * minimap.sharpen_boxmult; + } + if ( down ) { + val += p[+minimap.width] * minimap.sharpen_boxmult; + } + + ++p; + *q++ = val; + } +} + +static void MiniMapContrastBoost( int y ){ + int x; + float *q = &minimap.data1f[y * minimap.width]; + for ( x = 0; x < minimap.width; ++x ) + { + *q = *q * minimap.boost / ( ( minimap.boost - 1 ) * *q + 1 ); + ++q; + } +} + +static void MiniMapBrightnessContrast( int y ){ + int x; + float *q = &minimap.data1f[y * minimap.width]; + for ( x = 0; x < minimap.width; ++x ) + { + *q = *q * minimap.contrast + minimap.brightness; + ++q; + } +} + +void MiniMapMakeMinsMaxs( vec3_t mins_in, vec3_t maxs_in, float border, qboolean keepaspect ){ + vec3_t mins, maxs, extend; + VectorCopy( mins_in, mins ); + VectorCopy( maxs_in, maxs ); + + // line compatible to nexuiz mapinfo + Sys_Printf( "size %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] ); + + if ( keepaspect ) { + VectorSubtract( maxs, mins, extend ); + if ( extend[1] > extend[0] ) { + mins[0] -= ( extend[1] - extend[0] ) * 0.5; + maxs[0] += ( extend[1] - extend[0] ) * 0.5; + } + else + { + mins[1] -= ( extend[0] - extend[1] ) * 0.5; + maxs[1] += ( extend[0] - extend[1] ) * 0.5; + } + } + + /* border: amount of black area around the image */ + /* input: border, 1-2*border, border but we need border/(1-2*border) */ + + VectorSubtract( maxs, mins, extend ); + VectorScale( extend, border / ( 1 - 2 * border ), extend ); + + VectorSubtract( mins, extend, mins ); + VectorAdd( maxs, extend, maxs ); + + VectorCopy( mins, minimap.mins ); + VectorSubtract( maxs, mins, minimap.size ); + + // line compatible to nexuiz mapinfo + Sys_Printf( "size_texcoords %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] ); +} + +/* + MiniMapSetupBrushes() + determines solid non-sky brushes in the world + */ + +void MiniMapSetupBrushes( void ){ + SetupBrushesFlags( C_SOLID | C_SKY, C_SOLID, 0, 0 ); + // at least one must be solid + // none may be sky + // not all may be nodraw +} + +qboolean MiniMapEvaluateSampleOffsets( int *bestj, int *bestk, float *bestval ){ + float val, dx, dy; + int j, k; + + *bestj = *bestk = -1; + *bestval = 3; /* max possible val is 2 */ + + for ( j = 0; j < minimap.samples; ++j ) + for ( k = j + 1; k < minimap.samples; ++k ) + { + dx = minimap.sample_offsets[2 * j + 0] - minimap.sample_offsets[2 * k + 0]; + dy = minimap.sample_offsets[2 * j + 1] - minimap.sample_offsets[2 * k + 1]; + if ( dx > +0.5 ) { + dx -= 1; + } + if ( dx < -0.5 ) { + dx += 1; + } + if ( dy > +0.5 ) { + dy -= 1; + } + if ( dy < -0.5 ) { + dy += 1; + } + val = dx * dx + dy * dy; + if ( val < *bestval ) { + *bestj = j; + *bestk = k; + *bestval = val; + } + } + + return *bestval < 3; +} + +void MiniMapMakeSampleOffsets(){ + int i, j, k, jj, kk; + float val, valj, valk, sx, sy, rx, ry; + + Sys_Printf( "Generating good sample offsets (this may take a while)...\n" ); + + /* start with entirely random samples */ + for ( i = 0; i < minimap.samples; ++i ) + { + minimap.sample_offsets[2 * i + 0] = Random(); + minimap.sample_offsets[2 * i + 1] = Random(); + } + + for ( i = 0; i < 1000; ++i ) + { + if ( MiniMapEvaluateSampleOffsets( &j, &k, &val ) ) { + sx = minimap.sample_offsets[2 * j + 0]; + sy = minimap.sample_offsets[2 * j + 1]; + minimap.sample_offsets[2 * j + 0] = rx = Random(); + minimap.sample_offsets[2 * j + 1] = ry = Random(); + if ( !MiniMapEvaluateSampleOffsets( &jj, &kk, &valj ) ) { + valj = -1; + } + minimap.sample_offsets[2 * j + 0] = sx; + minimap.sample_offsets[2 * j + 1] = sy; + + sx = minimap.sample_offsets[2 * k + 0]; + sy = minimap.sample_offsets[2 * k + 1]; + minimap.sample_offsets[2 * k + 0] = rx; + minimap.sample_offsets[2 * k + 1] = ry; + if ( !MiniMapEvaluateSampleOffsets( &jj, &kk, &valk ) ) { + valk = -1; + } + minimap.sample_offsets[2 * k + 0] = sx; + minimap.sample_offsets[2 * k + 1] = sy; + + if ( valj > valk ) { + if ( valj > val ) { + /* valj is the greatest */ + minimap.sample_offsets[2 * j + 0] = rx; + minimap.sample_offsets[2 * j + 1] = ry; + i = -1; + } + else + { + /* valj is the greater and it is useless - forget it */ + } + } + else + { + if ( valk > val ) { + /* valk is the greatest */ + minimap.sample_offsets[2 * k + 0] = rx; + minimap.sample_offsets[2 * k + 1] = ry; + i = -1; + } + else + { + /* valk is the greater and it is useless - forget it */ + } + } + } + else{ + break; + } + } +} + +void MergeRelativePath( char *out, const char *absolute, const char *relative ){ + const char *endpos = absolute + strlen( absolute ); + while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) ) + --endpos; + while ( relative[0] == '.' && relative[1] == '.' && ( relative[2] == '/' || relative[2] == '\\' ) ) + { + relative += 3; + while ( endpos != absolute ) + { + --endpos; + if ( *endpos == '/' || *endpos == '\\' ) { + break; + } + } + while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) ) + --endpos; + } + memcpy( out, absolute, endpos - absolute ); + out[endpos - absolute] = '/'; + strcpy( out + ( endpos - absolute + 1 ), relative ); +} + +int MiniMapBSPMain( int argc, char **argv ){ + char minimapFilename[1024]; + char basename[1024]; + char path[1024]; + char relativeMinimapFilename[1024]; + qboolean autolevel; + float minimapSharpen; + float border; + byte *data4b, *p; + float *q; + int x, y; + int i; + miniMapMode_t mode; + vec3_t mins, maxs; + qboolean keepaspect; + + /* arg checking */ + if ( argc < 2 ) { + Sys_Printf( "Usage: q3map [-v] -minimap [-size n] [-sharpen f] [-samples n | -random n] [-o filename.tga] [-minmax Xmin Ymin Zmin Xmax Ymax Zmax] \n" ); + return 0; + } + + /* load the BSP first */ + strcpy( source, ExpandArg( argv[ argc - 1 ] ) ); + StripExtension( source ); + DefaultExtension( source, ".bsp" ); + Sys_Printf( "Loading %s\n", source ); + LoadShaderInfo(); + LoadBSPFile( source ); + + minimap.model = &bspModels[0]; + VectorCopy( minimap.model->mins, mins ); + VectorCopy( minimap.model->maxs, maxs ); + + *minimapFilename = 0; + minimapSharpen = game->miniMapSharpen; + minimap.width = minimap.height = game->miniMapSize; + border = game->miniMapBorder; + keepaspect = game->miniMapKeepAspect; + mode = game->miniMapMode; + + autolevel = qfalse; + minimap.samples = 1; + minimap.sample_offsets = NULL; + minimap.boost = 1.0; + minimap.brightness = 0.0; + minimap.contrast = 1.0; + + /* process arguments */ + for ( i = 1; i < ( argc - 1 ); i++ ) + { + if ( !strcmp( argv[ i ], "-size" ) ) { + minimap.width = minimap.height = atoi( argv[i + 1] ); + i++; + Sys_Printf( "Image size set to %i\n", minimap.width ); + } + else if ( !strcmp( argv[ i ], "-sharpen" ) ) { + minimapSharpen = atof( argv[i + 1] ); + i++; + Sys_Printf( "Sharpening coefficient set to %f\n", minimapSharpen ); + } + else if ( !strcmp( argv[ i ], "-samples" ) ) { + minimap.samples = atoi( argv[i + 1] ); + i++; + Sys_Printf( "Samples set to %i\n", minimap.samples ); + if ( minimap.sample_offsets ) { + free( minimap.sample_offsets ); + } + minimap.sample_offsets = malloc( 2 * sizeof( *minimap.sample_offsets ) * minimap.samples ); + MiniMapMakeSampleOffsets(); + } + else if ( !strcmp( argv[ i ], "-random" ) ) { + minimap.samples = atoi( argv[i + 1] ); + i++; + Sys_Printf( "Random samples set to %i\n", minimap.samples ); + if ( minimap.sample_offsets ) { + free( minimap.sample_offsets ); + } + minimap.sample_offsets = NULL; + } + else if ( !strcmp( argv[ i ], "-border" ) ) { + border = atof( argv[i + 1] ); + i++; + Sys_Printf( "Border set to %f\n", border ); + } + else if ( !strcmp( argv[ i ], "-keepaspect" ) ) { + keepaspect = qtrue; + Sys_Printf( "Keeping aspect ratio by letterboxing\n", border ); + } + else if ( !strcmp( argv[ i ], "-nokeepaspect" ) ) { + keepaspect = qfalse; + Sys_Printf( "Not keeping aspect ratio\n", border ); + } + else if ( !strcmp( argv[ i ], "-o" ) ) { + strcpy( minimapFilename, argv[i + 1] ); + i++; + Sys_Printf( "Output file name set to %s\n", minimapFilename ); + } + else if ( !strcmp( argv[ i ], "-minmax" ) && i < ( argc - 7 ) ) { + mins[0] = atof( argv[i + 1] ); + mins[1] = atof( argv[i + 2] ); + mins[2] = atof( argv[i + 3] ); + maxs[0] = atof( argv[i + 4] ); + maxs[1] = atof( argv[i + 5] ); + maxs[2] = atof( argv[i + 6] ); + i += 6; + Sys_Printf( "Map mins/maxs overridden\n" ); + } + else if ( !strcmp( argv[ i ], "-gray" ) ) { + mode = MINIMAP_MODE_GRAY; + Sys_Printf( "Writing as white-on-black image\n" ); + } + else if ( !strcmp( argv[ i ], "-black" ) ) { + mode = MINIMAP_MODE_BLACK; + Sys_Printf( "Writing as black alpha image\n" ); + } + else if ( !strcmp( argv[ i ], "-white" ) ) { + mode = MINIMAP_MODE_WHITE; + Sys_Printf( "Writing as white alpha image\n" ); + } + else if ( !strcmp( argv[ i ], "-boost" ) && i < ( argc - 2 ) ) { + minimap.boost = atof( argv[i + 1] ); + i++; + Sys_Printf( "Contrast boost set to %f\n", minimap.boost ); + } + else if ( !strcmp( argv[ i ], "-brightness" ) && i < ( argc - 2 ) ) { + minimap.brightness = atof( argv[i + 1] ); + i++; + Sys_Printf( "Brightness set to %f\n", minimap.brightness ); + } + else if ( !strcmp( argv[ i ], "-contrast" ) && i < ( argc - 2 ) ) { + minimap.contrast = atof( argv[i + 1] ); + i++; + Sys_Printf( "Contrast set to %f\n", minimap.contrast ); + } + else if ( !strcmp( argv[ i ], "-autolevel" ) ) { + autolevel = qtrue; + Sys_Printf( "Auto level enabled\n", border ); + } + else if ( !strcmp( argv[ i ], "-noautolevel" ) ) { + autolevel = qfalse; + Sys_Printf( "Auto level disabled\n", border ); + } + } + + MiniMapMakeMinsMaxs( mins, maxs, border, keepaspect ); + + if ( !*minimapFilename ) { + ExtractFileBase( source, basename ); + ExtractFilePath( source, path ); + sprintf( relativeMinimapFilename, game->miniMapNameFormat, basename ); + MergeRelativePath( minimapFilename, path, relativeMinimapFilename ); + Sys_Printf( "Output file name automatically set to %s\n", minimapFilename ); + } + ExtractFilePath( minimapFilename, path ); + Q_mkdir( path ); + + if ( minimapSharpen >= 0 ) { + minimap.sharpen_centermult = 8 * minimapSharpen + 1; + minimap.sharpen_boxmult = -minimapSharpen; + } + + minimap.data1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) ); + data4b = safe_malloc( minimap.width * minimap.height * 4 ); + if ( minimapSharpen >= 0 ) { + minimap.sharpendata1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) ); + } + + MiniMapSetupBrushes(); + + if ( minimap.samples <= 1 ) { + Sys_Printf( "\n--- MiniMapNoSupersampling (%d) ---\n", minimap.height ); + RunThreadsOnIndividual( minimap.height, qtrue, MiniMapNoSupersampling ); + } + else + { + if ( minimap.sample_offsets ) { + Sys_Printf( "\n--- MiniMapSupersampled (%d) ---\n", minimap.height ); + RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSupersampled ); + } + else + { + Sys_Printf( "\n--- MiniMapRandomlySupersampled (%d) ---\n", minimap.height ); + RunThreadsOnIndividual( minimap.height, qtrue, MiniMapRandomlySupersampled ); + } + } + + if ( minimap.boost != 1.0 ) { + Sys_Printf( "\n--- MiniMapContrastBoost (%d) ---\n", minimap.height ); + RunThreadsOnIndividual( minimap.height, qtrue, MiniMapContrastBoost ); + } + + if ( autolevel ) { + Sys_Printf( "\n--- MiniMapAutoLevel (%d) ---\n", minimap.height ); + float mi = 1, ma = 0; + float s, o; + + // TODO threads! + q = minimap.data1f; + for ( y = 0; y < minimap.height; ++y ) + for ( x = 0; x < minimap.width; ++x ) + { + float v = *q++; + if ( v < mi ) { + mi = v; + } + if ( v > ma ) { + ma = v; + } + } + if ( ma > mi ) { + s = 1 / ( ma - mi ); + o = mi / ( ma - mi ); + + // equations: + // brightness + contrast * v + // after autolevel: + // brightness + contrast * (v * s - o) + // = + // (brightness - contrast * o) + (contrast * s) * v + minimap.brightness = minimap.brightness - minimap.contrast * o; + minimap.contrast *= s; + + Sys_Printf( "Auto level: Brightness changed to %f\n", minimap.brightness ); + Sys_Printf( "Auto level: Contrast changed to %f\n", minimap.contrast ); + } + else{ + Sys_Printf( "Auto level: failed because all pixels are the same value\n" ); + } + } + + if ( minimap.brightness != 0 || minimap.contrast != 1 ) { + Sys_Printf( "\n--- MiniMapBrightnessContrast (%d) ---\n", minimap.height ); + RunThreadsOnIndividual( minimap.height, qtrue, MiniMapBrightnessContrast ); + } + + if ( minimap.sharpendata1f ) { + Sys_Printf( "\n--- MiniMapSharpen (%d) ---\n", minimap.height ); + RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSharpen ); + q = minimap.sharpendata1f; + } + else + { + q = minimap.data1f; + } + + Sys_Printf( "\nConverting..." ); + + switch ( mode ) + { + case MINIMAP_MODE_GRAY: + p = data4b; + for ( y = 0; y < minimap.height; ++y ) + for ( x = 0; x < minimap.width; ++x ) + { + byte b; + float v = *q++; + if ( v < 0 ) { + v = 0; + } + if ( v > 255.0 / 256.0 ) { + v = 255.0 / 256.0; + } + b = v * 256; + *p++ = b; + } + Sys_Printf( " writing to %s...", minimapFilename ); + WriteTGAGray( minimapFilename, data4b, minimap.width, minimap.height ); + break; + case MINIMAP_MODE_BLACK: + p = data4b; + for ( y = 0; y < minimap.height; ++y ) + for ( x = 0; x < minimap.width; ++x ) + { + byte b; + float v = *q++; + if ( v < 0 ) { + v = 0; + } + if ( v > 255.0 / 256.0 ) { + v = 255.0 / 256.0; + } + b = v * 256; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = b; + } + Sys_Printf( " writing to %s...", minimapFilename ); + WriteTGA( minimapFilename, data4b, minimap.width, minimap.height ); + break; + case MINIMAP_MODE_WHITE: + p = data4b; + for ( y = 0; y < minimap.height; ++y ) + for ( x = 0; x < minimap.width; ++x ) + { + byte b; + float v = *q++; + if ( v < 0 ) { + v = 0; + } + if ( v > 255.0 / 256.0 ) { + v = 255.0 / 256.0; + } + b = v * 256; + *p++ = 255; + *p++ = 255; + *p++ = 255; + *p++ = b; + } + Sys_Printf( " writing to %s...", minimapFilename ); + WriteTGA( minimapFilename, data4b, minimap.width, minimap.height ); + break; + } + + Sys_Printf( " done.\n" ); + + /* return to sender */ + return 0; +} diff --git a/tools/quake3/q3map2/model.c b/tools/quake3/q3map2/model.c index 55948c5c..68897e48 100644 --- a/tools/quake3/q3map2/model.c +++ b/tools/quake3/q3map2/model.c @@ -389,10 +389,19 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade { dv->lightmap[ j ][ 0 ] = 0.0f; dv->lightmap[ j ][ 1 ] = 0.0f; - dv->color[ j ][ 0 ] = color[ 0 ]; - dv->color[ j ][ 1 ] = color[ 1 ]; - dv->color[ j ][ 2 ] = color[ 2 ]; - dv->color[ j ][ 3 ] = color[ 3 ]; + if ( spawnFlags & 32 ) { // spawnflag 32: model color -> alpha hack + dv->color[ j ][ 0 ] = 255.0f; + dv->color[ j ][ 1 ] = 255.0f; + dv->color[ j ][ 2 ] = 255.0f; + dv->color[ j ][ 3 ] = color[ 0 ] * 0.3f + color[ 1 ] * 0.59f + color[ 2 ] * 0.11f; + } + else + { + dv->color[ j ][ 0 ] = color[ 0 ]; + dv->color[ j ][ 1 ] = color[ 1 ]; + dv->color[ j ][ 2 ] = color[ 2 ]; + dv->color[ j ][ 3 ] = color[ 3 ]; + } } } diff --git a/tools/quake3/q3map2/prtfile.c b/tools/quake3/q3map2/prtfile.c index eeb3a800..ce2cff16 100644 --- a/tools/quake3/q3map2/prtfile.c +++ b/tools/quake3/q3map2/prtfile.c @@ -64,6 +64,40 @@ void WriteFloat( FILE *f, vec_t v ){ } } +void CountVisportals_r( node_t *node ){ + int s; + portal_t *p; + winding_t *w; + vec3_t normal; + vec_t dist; + + // decision node + if ( node->planenum != PLANENUM_LEAF ) { + CountVisportals_r( node->children[0] ); + CountVisportals_r( node->children[1] ); + return; + } + + if ( node->opaque ) { + return; + } + + for ( p = node->portals ; p ; p = p->next[s] ) + { + w = p->winding; + s = ( p->nodes[1] == node ); + if ( w && p->nodes[0] == node ) { + if ( !PortalPassable( p ) ) { + continue; + } + if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) { + continue; + } + ++num_visportals; + } + } +} + /* ================= WritePortalFile_r @@ -95,6 +129,10 @@ void WritePortalFile_r( node_t *node ){ if ( !PortalPassable( p ) ) { continue; } + if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) { + continue; + } + --num_visportals; // write out to the file // sometimes planes get turned around when they are very near @@ -111,7 +149,7 @@ void WritePortalFile_r( node_t *node ){ } /* ydnar: added this change to make antiportals work */ - if ( p->compileFlags & C_HINT ) { + if( p->compileFlags & C_HINT ) { fprintf( pf, "1 " ); } else{ @@ -133,6 +171,40 @@ void WritePortalFile_r( node_t *node ){ } +void CountSolidFaces_r( node_t *node ){ + int s; + portal_t *p; + winding_t *w; + + // decision node + if ( node->planenum != PLANENUM_LEAF ) { + CountSolidFaces_r( node->children[0] ); + CountSolidFaces_r( node->children[1] ); + return; + } + + if ( node->opaque ) { + return; + } + + for ( p = node->portals ; p ; p = p->next[s] ) + { + w = p->winding; + s = ( p->nodes[1] == node ); + if ( w ) { + if ( PortalPassable( p ) ) { + continue; + } + if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) { + continue; + } + // write out to the file + + ++num_solidfaces; + } + } +} + /* ================= WriteFaceFile_r @@ -162,6 +234,9 @@ void WriteFaceFile_r( node_t *node ){ if ( PortalPassable( p ) ) { continue; } + if(p->nodes[0]->cluster == p->nodes[1]->cluster) + continue; + --num_visportals; // write out to the file if ( p->nodes[0] == node ) { @@ -198,14 +273,26 @@ void WriteFaceFile_r( node_t *node ){ NumberLeafs_r ================ */ -void NumberLeafs_r( node_t *node ){ +void NumberLeafs_r( node_t *node, int c ){ +#if 0 portal_t *p; - +#endif if ( node->planenum != PLANENUM_LEAF ) { // decision node node->cluster = -99; - NumberLeafs_r( node->children[0] ); - NumberLeafs_r( node->children[1] ); + + if ( node->has_structural_children ) { + NumberLeafs_r( node->children[0], c ); + NumberLeafs_r( node->children[1], c ); + } + else + { + if ( c < 0 ) { + c = num_visclusters++; + } + NumberLeafs_r( node->children[0], c ); + NumberLeafs_r( node->children[1], c ); + } return; } @@ -217,9 +304,13 @@ void NumberLeafs_r( node_t *node ){ return; } - node->cluster = num_visclusters; - num_visclusters++; + if ( c < 0 ) { + c = num_visclusters++; + } + node->cluster = c; + +#if 0 // count the portals for ( p = node->portals ; p ; ) { @@ -240,6 +331,7 @@ void NumberLeafs_r( node_t *node ){ p = p->next[1]; } } +#endif } @@ -256,7 +348,9 @@ void NumberClusters( tree_t *tree ) { Sys_FPrintf( SYS_VRB,"--- NumberClusters ---\n" ); // set the cluster field in every leaf and count the total number of portals - NumberLeafs_r( tree->headnode ); + NumberLeafs_r( tree->headnode, -1 ); + CountVisportals_r( tree->headnode ); + CountSolidFaces_r( tree->headnode ); Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters ); Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals ); diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index f0adf73b..65b765fe 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -202,6 +202,7 @@ #define HINT_PRIORITY 1000 /* ydnar: force hint splits first and antiportal/areaportal splits last */ #define ANTIPORTAL_PRIORITY -1000 #define AREAPORTAL_PRIORITY -1000 +#define DETAIL_PRIORITY -3000 #define PSIDE_FRONT 1 #define PSIDE_BACK 2 @@ -548,6 +549,13 @@ typedef struct surfaceParm_s } surfaceParm_t; +typedef enum +{ + MINIMAP_MODE_GRAY, + MINIMAP_MODE_BLACK, + MINIMAP_MODE_WHITE +} +miniMapMode_t; typedef struct game_s { @@ -565,6 +573,12 @@ typedef struct game_s int lightmapSize; /* bsp lightmap width/height */ float lightmapGamma; /* default lightmap gamma */ float lightmapCompensate; /* default lightmap compensate value */ + int miniMapSize; /* minimap size */ + float miniMapSharpen; /* minimap sharpening coefficient */ + float miniMapBorder; /* minimap border amount */ + qboolean miniMapKeepAspect; /* minimap keep aspect ratio by letterboxing */ + miniMapMode_t miniMapMode; /* minimap mode */ + char *miniMapNameFormat; /* minimap name format */ char *bspIdent; /* 4-letter bsp file prefix */ int bspVersion; /* bsp version to use */ qboolean lumpSwap; /* cod-style len/ofs order */ @@ -789,7 +803,7 @@ typedef struct face_s struct face_s *next; int planenum; int priority; - qboolean checked; + //qboolean checked; int compileFlags; winding_t *w; } @@ -801,6 +815,7 @@ typedef struct plane_s vec3_t normal; vec_t dist; int type; + int counter; struct plane_s *hash_chain; } plane_t; @@ -1115,6 +1130,8 @@ typedef struct node_s entity_t *occupant; /* for leak file testing */ struct portal_s *portals; /* also on nodes during construction */ + + qboolean has_structural_children; } node_t; @@ -1480,6 +1497,8 @@ int BSPInfoMain( int argc, char **argv ); /* bsp_scale.c */ int ScaleBSPMain( int argc, char **argv ); +/* minimap.c */ +int MiniMapBSPMain( int argc, char **argv ); /* convert_bsp.c */ int ConvertBSPMain( int argc, char **argv ); @@ -1747,6 +1766,7 @@ void DirtyRawLightmap( int num ); void IlluminateRawLightmap( int num ); void IlluminateVertexes( int num ); +void SetupBrushesFlags( unsigned int mask_any, unsigned int test_any, unsigned int mask_all, unsigned int test_all ); void SetupBrushes( void ); void SetupClusters( void ); qboolean ClusterVisible( int a, int b ); @@ -1802,6 +1822,7 @@ void EmitVertexRemapShader( char *from, char *to ); void LoadShaderInfo( void ); shaderInfo_t *ShaderInfoForShader( const char *shader ); +shaderInfo_t *ShaderInfoForShaderNull( const char *shader ); /* bspfile_abstract.c */ @@ -1876,7 +1897,7 @@ Q_EXTERN game_t games[] , #include "game_tremulous.h" /*LinuxManMikeC: must be after game_quake3.h, depends on #define's set in it */ , - #include "game_unvanquished.h" /* must be after game_quake3.h as they share defines! */ + #include "game_unvanquished.h" /* must be after game_tremulous.h as they share defines! */ , #include "game_tenebrae.h" , @@ -1898,7 +1919,7 @@ Q_EXTERN game_t games[] , #include "game_reaction.h" /* must be after game_quake3.h */ , - #include "game__null.h" /* null game (must be last item) */ + #include "game__null.h" /* null game (must be last item) */ }; #endif Q_EXTERN game_t *game Q_ASSIGN( &games[ 0 ] ); @@ -1946,6 +1967,8 @@ Q_EXTERN qboolean nofog Q_ASSIGN( qfalse ); Q_EXTERN qboolean noHint Q_ASSIGN( qfalse ); /* ydnar */ Q_EXTERN qboolean renameModelShaders Q_ASSIGN( qfalse ); /* ydnar */ Q_EXTERN qboolean skyFixHack Q_ASSIGN( qfalse ); /* ydnar */ +Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse ); /* 27 */ +Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse ); /* div0 */ Q_EXTERN int patchSubdivisions Q_ASSIGN( 8 ); /* ydnar: -patchmeta subdivisions */ @@ -2075,14 +2098,16 @@ Q_EXTERN m4x4_t skyboxTransform; ------------------------------------------------------------------------------- */ /* commandline arguments */ -Q_EXTERN qboolean fastvis; -Q_EXTERN qboolean noPassageVis; -Q_EXTERN qboolean passageVisOnly; -Q_EXTERN qboolean mergevis; -Q_EXTERN qboolean nosort; -Q_EXTERN qboolean saveprt; -Q_EXTERN qboolean hint; /* ydnar */ -Q_EXTERN char inbase[ MAX_QPATH ]; +Q_EXTERN qboolean fastvis; +Q_EXTERN qboolean noPassageVis; +Q_EXTERN qboolean passageVisOnly; +Q_EXTERN qboolean mergevis; +Q_EXTERN qboolean mergevisportals; +Q_EXTERN qboolean nosort; +Q_EXTERN qboolean saveprt; +Q_EXTERN qboolean hint; /* ydnar */ +Q_EXTERN char inbase[ MAX_QPATH ]; +Q_EXTERN char globalCelShader[ MAX_QPATH ]; /* other bits */ Q_EXTERN int totalvis; @@ -2368,7 +2393,7 @@ Q_EXTERN int numBSPBrushSides Q_ASSIGN( 0 ); Q_EXTERN bspBrushSide_t bspBrushSides[ MAX_MAP_BRUSHSIDES ]; Q_EXTERN int numBSPLightBytes Q_ASSIGN( 0 ); -Q_EXTERN byte *bspLightBytes Q_ASSIGN( NULL ); +Q_EXTERN byte *bspLightBytes Q_ASSIGN( NULL ); //% Q_EXTERN int numBSPGridPoints Q_ASSIGN( 0 ); //% Q_EXTERN byte *bspGridPoints Q_ASSIGN( NULL ); @@ -2380,7 +2405,7 @@ Q_EXTERN int numBSPVisBytes Q_ASSIGN( 0 ); Q_EXTERN byte bspVisBytes[ MAX_MAP_VISIBILITY ]; Q_EXTERN int numBSPDrawVerts Q_ASSIGN( 0 ); -Q_EXTERN bspDrawVert_t *bspDrawVerts Q_ASSIGN( NULL ); +Q_EXTERN bspDrawVert_t *bspDrawVerts Q_ASSIGN( NULL ); Q_EXTERN int numBSPDrawIndexes Q_ASSIGN( 0 ); Q_EXTERN int bspDrawIndexes[ MAX_MAP_DRAW_INDEXES ]; diff --git a/tools/quake3/q3map2/q3map2.vcxproj b/tools/quake3/q3map2/q3map2.vcxproj index dd1120d7..bcde1258 100644 --- a/tools/quake3/q3map2/q3map2.vcxproj +++ b/tools/quake3/q3map2/q3map2.vcxproj @@ -167,6 +167,7 @@ + @@ -240,4 +241,4 @@ - \ No newline at end of file + diff --git a/tools/quake3/q3map2/shaders.c b/tools/quake3/q3map2/shaders.c index 153f3daa..160a5bb5 100644 --- a/tools/quake3/q3map2/shaders.c +++ b/tools/quake3/q3map2/shaders.c @@ -801,6 +801,13 @@ static void LoadShaderImages( shaderInfo_t *si ){ finds a shaderinfo for a named shader */ +shaderInfo_t *ShaderInfoForShaderNull( const char *shaderName ){ + if ( !strcmp( shaderName, "noshader" ) ) { + return NULL; + } + return ShaderInfoForShader( shaderName ); +} + shaderInfo_t *ShaderInfoForShader( const char *shaderName ){ int i; shaderInfo_t *si; @@ -1458,7 +1465,7 @@ static void ParseShaderFile( const char *filename ){ si->lightmapSampleSize = atoi( token ); } - /* q3map_lightmapSampleSffset */ + /* q3map_lightmapSampleOffset */ else if ( !Q_stricmp( token, "q3map_lightmapSampleOffset" ) ) { GetTokenAppend( shaderText, qfalse ); si->lightmapSampleOffset = atof( token ); diff --git a/tools/quake3/q3map2/vis.c b/tools/quake3/q3map2/vis.c index 5b38d12e..b301507d 100644 --- a/tools/quake3/q3map2/vis.c +++ b/tools/quake3/q3map2/vis.c @@ -1086,6 +1086,9 @@ int VisMain( int argc, char **argv ){ else if ( !strcmp( argv[i], "-merge" ) ) { Sys_Printf( "merge = true\n" ); mergevis = qtrue; + } else if (!strcmp(argv[i], "-mergeportals")) { + Sys_Printf ("mergeportals = true\n"); + mergevisportals = qtrue; } else if ( !strcmp( argv[i], "-nopassage" ) ) { Sys_Printf( "nopassage = true\n" ); @@ -1150,9 +1153,12 @@ int VisMain( int argc, char **argv ){ /* ydnar: for getting far plane */ ParseEntities(); - - if ( mergevis ) { + + if( mergevis ) { MergeLeaves(); + } + + if( mergevis || mergevisportals ) { MergeLeafPortals(); }