From fbb0ae361bdb1ba72bd3e0810fd104c7df4cc4b6 Mon Sep 17 00:00:00 2001 From: div0 Date: Wed, 8 Oct 2008 09:05:25 +0000 Subject: [PATCH] renamed roughmap to radarmap; automatically sharpen it git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4658 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/Main.qc | 18 ++- data/qcsrc/client/csqc_constants.qc | 6 + data/qcsrc/common/util.qc | 84 ++++++++++++- data/qcsrc/common/util.qh | 8 +- data/qcsrc/server/gamecommand.qc | 175 +++++++++++++++++++++------- 5 files changed, 240 insertions(+), 51 deletions(-) diff --git a/data/qcsrc/client/Main.qc b/data/qcsrc/client/Main.qc index c6919ca96..8992bee2b 100644 --- a/data/qcsrc/client/Main.qc +++ b/data/qcsrc/client/Main.qc @@ -542,18 +542,24 @@ void CSQC_Ent_Remove() void Gamemode_Init() { - get_mi_min_max(); - mi_center = (mi_min + mi_max) * 0.5; - mi_scale = mi_max - mi_min; - minimapname = strzone(strcat("gfx/", mi_shortname, "_mini.tga")); + get_mi_min_max_texcoords(1); // try the CLEVER way first + minimapname = strcat("gfx/", mi_shortname, "_radar.tga"); shortmapname = mi_shortname; if(precache_pic(minimapname) == "") { - strunzone(minimapname); - minimapname = ""; // FAIL + // but maybe we have a non-clever minimap + minimapname = strcat("gfx/", mi_shortname, "_mini.tga"); + if(precache_pic(minimapname) == "") + minimapname = ""; // FAIL + else + get_mi_min_max_texcoords(0); // load new texcoords } + mi_center = (mi_min + mi_max) * 0.5; + mi_scale = mi_max - mi_min; + minimapname = strzone(minimapname); + if(gametype == GAME_ONSLAUGHT) { print(strcat("Using ", minimapname, " as minimap.\n")); precache_pic("gfx/ons-cp-neutral.tga"); diff --git a/data/qcsrc/client/csqc_constants.qc b/data/qcsrc/client/csqc_constants.qc index fdb5f93e9..94505c6d3 100644 --- a/data/qcsrc/client/csqc_constants.qc +++ b/data/qcsrc/client/csqc_constants.qc @@ -177,3 +177,9 @@ const float DRAWFLAG_MIPMAP = 0x100; // only for R_BeginPolygon #define SOLID_SLIDEBOX 3 // touch on edge, but not an onground #define SOLID_BSP 4 // bsp clip, touch on edge, block #define SOLID_CORPSE 5 // same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters) + +float MOVE_NORMAL = 0; // same as FALSE +float MOVE_NOMONSTERS = 1; // same as TRUE +float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE +float MOVE_HITMODEL = 4; +float MOVE_WORLDONLY = 3; diff --git a/data/qcsrc/common/util.qc b/data/qcsrc/common/util.qc index 7b9903b73..a4be2e7d9 100644 --- a/data/qcsrc/common/util.qc +++ b/data/qcsrc/common/util.qc @@ -713,9 +713,9 @@ float cvar_value_issafe(string s) } #ifndef MENUQC -void get_mi_min_max() +void get_mi_min_max(float mode) { - vector extend; + vector mi, ma; if(mi_shortname) strunzone(mi_shortname); @@ -726,14 +726,90 @@ void get_mi_min_max() mi_shortname = substring(mi_shortname, 0, strlen(mi_shortname) - 4); mi_shortname = strzone(mi_shortname); - mi_min = world.mins; - mi_max = world.maxs; +#ifdef CSQC + mi = world.mins; + ma = world.maxs; +#else + mi = world.absmin; + ma = world.absmax; +#endif + + mi_min = mi; + mi_max = ma; MapInfo_Get_ByName(mi_shortname, 0, 0); if(MapInfo_Map_mins_x < MapInfo_Map_maxs_x) { mi_min = MapInfo_Map_mins; mi_max = MapInfo_Map_maxs; } + else + { + // not specified + if(mode) + { + // be clever + tracebox('1 0 0' * mi_x, + '0 1 0' * mi_y + '0 0 1' * mi_z, + '0 1 0' * ma_y + '0 0 1' * ma_z, + '1 0 0' * ma_x, + MOVE_WORLDONLY, + world); + if(!trace_startsolid) + mi_min_x = trace_endpos_x; + + tracebox('0 1 0' * mi_y, + '1 0 0' * mi_x + '0 0 1' * mi_z, + '1 0 0' * ma_x + '0 0 1' * ma_z, + '0 1 0' * ma_y, + MOVE_WORLDONLY, + world); + if(!trace_startsolid) + mi_min_y = trace_endpos_y; + + tracebox('0 0 1' * mi_z, + '1 0 0' * mi_x + '0 1 0' * mi_y, + '1 0 0' * ma_x + '0 1 0' * ma_y, + '0 0 1' * ma_z, + MOVE_WORLDONLY, + world); + if(!trace_startsolid) + mi_min_z = trace_endpos_z; + + tracebox('1 0 0' * ma_x, + '0 1 0' * mi_y + '0 0 1' * mi_z, + '0 1 0' * ma_y + '0 0 1' * ma_z, + '1 0 0' * mi_x, + MOVE_WORLDONLY, + world); + if(!trace_startsolid) + mi_max_x = trace_endpos_x; + + tracebox('0 1 0' * ma_y, + '1 0 0' * mi_x + '0 0 1' * mi_z, + '1 0 0' * ma_x + '0 0 1' * ma_z, + '0 1 0' * mi_y, + MOVE_WORLDONLY, + world); + if(!trace_startsolid) + mi_max_y = trace_endpos_y; + + tracebox('0 0 1' * ma_z, + '1 0 0' * mi_x + '0 1 0' * mi_y, + '1 0 0' * ma_x + '0 1 0' * ma_y, + '0 0 1' * mi_z, + MOVE_WORLDONLY, + world); + if(!trace_startsolid) + mi_max_z = trace_endpos_z; + } + } +} + +void get_mi_min_max_texcoords(float mode) +{ + vector extend; + + get_mi_min_max(mode); mi_picmin = mi_min; mi_picmax = mi_max; diff --git a/data/qcsrc/common/util.qh b/data/qcsrc/common/util.qh index 2608c48d0..216a2fdd2 100644 --- a/data/qcsrc/common/util.qh +++ b/data/qcsrc/common/util.qh @@ -83,16 +83,22 @@ void cvar_settemp(string pKey, string pValue); void cvar_settemp_restore(); #ifndef MENUQC +// modes: 0 = trust q3map2 (_mini images) +// 1 = trust tracebox (_radar images) +// in both modes, mapinfo's "size" overrides + string mi_shortname; vector mi_min; vector mi_max; +void get_mi_min_max(float mode); + vector mi_picmin; // adjusted mins that map to the picture (square) vector mi_picmax; // adjusted maxs that map to the picture (square) vector mi_pictexcoord0; // texcoords of the image corners (after transforming, these are 2D coords too) vector mi_pictexcoord1; // texcoords of the image corners (after transforming, these are 2D coords too) vector mi_pictexcoord2; // texcoords of the image corners (after transforming, these are 2D coords too) vector mi_pictexcoord3; // texcoords of the image corners (after transforming, these are 2D coords too) -void get_mi_min_max(); +void get_mi_min_max_texcoords(float mode); #endif #define FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(x) void reference_##x() { x = x; } diff --git a/data/qcsrc/server/gamecommand.qc b/data/qcsrc/server/gamecommand.qc index 1a6bb3d5f..9dbb8eb15 100644 --- a/data/qcsrc/server/gamecommand.qc +++ b/data/qcsrc/server/gamecommand.qc @@ -27,7 +27,7 @@ float FullTraceFraction(vector a, vector mi, vector ma, vector b) } } -float RoughMapAtPoint(float x, float y, float w, float h) +float RadarMapAtPoint(float x, float y, float w, float h) { vector a, b, mi, ma; mi = '0 0 0'; @@ -37,7 +37,7 @@ float RoughMapAtPoint(float x, float y, float w, float h) return floor(FullTraceFraction(a, mi, ma, b) / (world.maxs_z - world.mins_z) * 255); } #else -float RoughMapAtPoint(float x, float y, float w, float h, float zmin, float zsize) +float RadarMapAtPoint(float x, float y, float w, float h, float zmin, float zsize) { vector o, mi, ma; float i, r; @@ -63,19 +63,77 @@ float RoughMapAtPoint(float x, float y, float w, float h, float zmin, float zsiz if(trace_startsolid) ++r; } - return r; // 0 .. 255 + return r / 255.0; // 0 .. 1 } #endif string doublehex = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"; -entity roughmapper; +float RADAR_WIDTH = 512; +float RADAR_HEIGHT = 512; +float sharpen_buffer[RADAR_WIDTH * 3]; + +void sharpen_set(float x, float v) +{ + sharpen_buffer[x + 2 * RADAR_WIDTH] = v; +} + +float sharpen_getpixel(float x, float y) +{ + if(x < 0) + return 0; + if(x >= RADAR_WIDTH) + return 0; + if(y < 0) + return 0; + if(y > 2) + return 0; + return sharpen_buffer[x + y * RADAR_WIDTH]; +} + +float sharpen_get(float x, float a) +{ + float sum; + sum = sharpen_getpixel(x, 1); + if(a == 0) + return sum; + sum *= (8 + 1/a); + sum -= sharpen_getpixel(x - 1, 0); + sum -= sharpen_getpixel(x - 1, 1); + sum -= sharpen_getpixel(x - 1, 2); + sum -= sharpen_getpixel(x + 1, 0); + sum -= sharpen_getpixel(x + 1, 1); + sum -= sharpen_getpixel(x + 1, 2); + sum -= sharpen_getpixel(x, 0); + sum -= sharpen_getpixel(x, 2); + return bound(0, sum * a, 1); +} + +void sharpen_shift() +{ + float i; + for(i = 0; i < RADAR_WIDTH; ++i) + { + sharpen_buffer[i] = sharpen_buffer[i + RADAR_WIDTH]; + sharpen_buffer[i + RADAR_WIDTH] = sharpen_buffer[i + 2 * RADAR_WIDTH]; + sharpen_buffer[i + 2 * RADAR_WIDTH] = 0; + } +} + +void sharpen_init() +{ + float i; + for(i = 0; i < 3 * RADAR_WIDTH; ++i) + sharpen_buffer[i] = 0; +} + +entity radarmapper; // rough map entity // cnt: current line // size: pixel width/height // maxs: cell width/height // frame: counter -void RoughMap_Think() +void RadarMap_Think() { float i, x, l; string si; @@ -83,15 +141,15 @@ void RoughMap_Think() if(self.frame == 0) { // initialize - get_mi_min_max(); - self.size_x = 512; - self.size_y = 512; + get_mi_min_max_texcoords(1); + self.size_x = RADAR_WIDTH; + self.size_y = RADAR_HEIGHT; self.mins = mi_picmin; self.maxs_x = (mi_picmax_x - mi_picmin_x) / self.size_x; self.maxs_y = (mi_picmax_y - mi_picmin_y) / self.size_y; self.maxs_z = mi_max_z - mi_min_z; print("Picture mins/maxs: ", ftos(self.maxs_x), " and ", ftos(self.maxs_y), " should match\n"); - self.netname = strzone(strcat("gfx/", mi_shortname, "_mini.xpm")); + self.netname = strzone(strcat("gfx/", mi_shortname, "_radar.xpm")); if(!(self.count & 1)) { self.cnt = fopen(self.netname, FILE_READ); @@ -105,13 +163,13 @@ void RoughMap_Think() else if(self.count & 2) { if(self.count & 1) - localcmd("defer 1 \"sv_cmd roughmap --force --loop\"\n"); + localcmd(strcat("defer 1 \"sv_cmd radarmap --force --loop", ftos(self.ltime), "\"\n")); else - localcmd("defer 1 \"sv_cmd roughmap --loop\"\n"); + localcmd(strcat("defer 1 \"sv_cmd radarmap --loop ", ftos(self.ltime), "\"\n")); GotoNextMap(); } remove(self); - roughmapper = world; + radarmapper = world; return; } } @@ -120,12 +178,12 @@ void RoughMap_Think() { print("Error writing ", self.netname, "\n"); remove(self); - roughmapper = world; + radarmapper = world; return; } print("Writing to ", self.netname, "...\n"); fputs(self.cnt, "/* XPM */\n"); - fputs(self.cnt, "static char *RoughMap[] = {\n"); + fputs(self.cnt, "static char *RadarMap[] = {\n"); fputs(self.cnt, "/* columns rows colors chars-per-pixel */\n"); fputs(self.cnt, strcat("\"", ftos(self.size_x), " ", ftos(self.size_y), " 256 2\",\n")); for(i = 0; i < 256; ++i) @@ -135,23 +193,57 @@ void RoughMap_Think() } self.frame += 1; self.nextthink = time; + sharpen_init(); } else if(self.frame <= self.size_y) { - // write a pixel line - fputs(self.cnt, "\""); + // fill the sharpen buffer with this line + sharpen_shift(); for(x = 0; x < self.size_x; ++x) { - l = RoughMapAtPoint(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z); - fputs(self.cnt, substring(doublehex, 2 * l, 2)); + l = RadarMapAtPoint(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z); + sharpen_set(x, l); + } + + // do we have enough lines? + if(self.frame >= 2) + { + // write a pixel line + fputs(self.cnt, "\""); + for(x = 0; x < self.size_x; ++x) + { + l = sharpen_get(x, self.ltime); + fputs(self.cnt, substring(doublehex, 2 * floor(l * 255.0 + 0.5), 2)); + } + if(self.frame == self.size_y) + fputs(self.cnt, "\"\n"); + else + { + fputs(self.cnt, "\",\n"); + print(ftos(self.size_y - self.frame), " lines left\n"); + } } + + // is this the last line? then write back the missing line if(self.frame == self.size_y) - fputs(self.cnt, "\"\n"); - else { - fputs(self.cnt, "\",\n"); - print(ftos(self.size_y - self.frame), " lines left\n"); + sharpen_shift(); + // write a pixel line + fputs(self.cnt, "\""); + for(x = 0; x < self.size_x; ++x) + { + l = sharpen_get(x, self.ltime); + fputs(self.cnt, substring(doublehex, 2 * floor(l * 255.0 + 0.5), 2)); + } + if(self.frame == self.size_y) + fputs(self.cnt, "\"\n"); + else + { + fputs(self.cnt, "\",\n"); + print(ftos(self.size_y - self.frame), " lines left\n"); + } } + self.frame += 1; self.nextthink = time; } @@ -168,35 +260,38 @@ void RoughMap_Think() else if(self.count & 2) { if(self.count & 1) - localcmd("defer 1 \"sv_cmd roughmap --force --loop\"\n"); + localcmd(strcat("defer 1 \"sv_cmd radarmap --force --loop", ftos(self.ltime), "\"\n")); else - localcmd("defer 1 \"sv_cmd roughmap --loop\"\n"); + localcmd(strcat("defer 1 \"sv_cmd radarmap --loop ", ftos(self.ltime), "\"\n")); GotoNextMap(); } remove(self); - roughmapper = world; + radarmapper = world; } } -void RoughMap(float argc) +void RadarMap(float argc) { - if(roughmapper) + if(radarmapper) return; float i; - roughmapper = spawn(); - roughmapper.classname = "roughmapper"; - roughmapper.think = RoughMap_Think; - roughmapper.nextthink = time; - roughmapper.count = 0; + radarmapper = spawn(); + radarmapper.classname = "radarmapper"; + radarmapper.think = RadarMap_Think; + radarmapper.nextthink = time; + radarmapper.count = 0; + radarmapper.ltime = 1; for(i = 1; i < argc; ++i) { if(argv(i) == "--force") - roughmapper.count |= 1; - if(argv(i) == "--loop") - roughmapper.count |= 2; - if(argv(i) == "--quit") - roughmapper.count |= 4; + radarmapper.count |= 1; + else if(argv(i) == "--loop") + radarmapper.count |= 2; + else if(argv(i) == "--quit") + radarmapper.count |= 4; + else + radarmapper.ltime = stof(argv(i)); } } @@ -376,7 +471,7 @@ void GameCommand(string command) print(" loaddb filename\n"); print(" allready\n"); print(" effectindexdump\n"); - print(" roughmap\n"); + print(" radarmap\n"); print(" bbox\n"); GameCommand_Vote("help", world); GameCommand_Ban("help"); @@ -560,9 +655,9 @@ void GameCommand(string command) EffectIndexDump(); return; } - if (argv(0) == "roughmap") + if (argv(0) == "radarmap") { - RoughMap(argc); + RadarMap(argc); return; } if (argv(0) == "bbox") -- 2.39.2