vhlt/hlvis/vis.cpp
2016-09-21 00:07:53 +03:00

2082 lines
55 KiB
C++

/*
VISIBLE INFORMATION SET -aka- V I S
Code based on original code from Valve Software,
Modified by Sean "Zoner" Cavanaugh (seanc@gearboxsoftware.com) with permission.
Modified by Tony "Merl" Moore (merlinis@bigpond.net.au)
Contains code by Skyler "Zipster" York (zipster89134@hotmail.com) - Included with permission.
*/
#include "vis.h"
#ifdef ZHLT_LANGFILE
#ifdef SYSTEM_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#endif
#ifdef ZHLT_NETVIS
#include "zlib.h"
#endif
/*
NOTES
*/
int g_numportals = 0;
unsigned g_portalleafs = 0;
portal_t* g_portals;
leaf_t* g_leafs;
#ifdef ZHLT_DETAILBRUSH
int *g_leafstarts;
int *g_leafcounts;
int g_leafcount_all;
#endif
// AJM: MVD
#ifdef HLVIS_MAXDIST
#ifndef HLVIS_MAXDIST_NEW
byte* g_mightsee;
visblocker_t g_visblockers[MAX_VISBLOCKERS];
int g_numvisblockers = 0;
#endif
#endif
//
static byte* vismap;
static byte* vismap_p;
static byte* vismap_end; // past visfile
static int originalvismapsize;
byte* g_uncompressed; // [bitbytes*portalleafs]
unsigned g_bitbytes; // (portalleafs+63)>>3
unsigned g_bitlongs;
bool g_fastvis = DEFAULT_FASTVIS;
bool g_fullvis = DEFAULT_FULLVIS;
bool g_estimate = DEFAULT_ESTIMATE;
bool g_chart = DEFAULT_CHART;
bool g_info = DEFAULT_INFO;
#ifdef HLVIS_MAXDIST
// AJM: MVD
unsigned int g_maxdistance = DEFAULT_MAXDISTANCE_RANGE;
//bool g_postcompile = DEFAULT_POST_COMPILE;
//
#endif
#ifdef HLVIS_OVERVIEW
const int g_overview_max = MAX_MAP_ENTITIES;
overview_t g_overview[g_overview_max];
int g_overview_count = 0;
leafinfo_t* g_leafinfos = NULL;
#endif
#ifdef ZHLT_PROGRESSFILE // AJM
char* g_progressfile = DEFAULT_PROGRESSFILE; // "-progressfile path"
#endif
static int totalvis = 0;
#if ZHLT_ZONES
Zones* g_Zones;
#endif
#ifdef ZHLT_NETVIS
// -- these are definitions and initializations of C/CPP common variables
volatile int g_visportalindex = UNINITIALIZED_PORTAL_INDEX; // a client's portal index : current portalindex being worked on
volatile int g_visportals = 0; // the total portals in the map
volatile int g_visleafs = 0; // the total portal leafs in the map
volatile int g_vislocalportal = 0; // number of portals solved locally
volatile enum vis_states g_visstate = VIS_STARTUP; // current step of execution
volatile enum vis_modes g_vismode = VIS_MODE_NULL; // style of execution (client or server)
volatile int g_visleafthread = 0; // control flag (are we ready to leafthread)
unsigned int g_rate = DEFAULT_NETVIS_RATE;
volatile double g_starttime = 0; // Start time (from I_FloatTime())
volatile unsigned long g_idletime = 0; // Accumulated idle time in milliseconds (rolls over after 46.7 days, hopefully a vis client wont run that long)
volatile unsigned long g_serverindex = 0; // client only variable, server index for calculating percentage indicators on the client
short g_port = DEFAULT_NETVIS_PORT;
const char* g_server_addr = NULL;
volatile bool g_bsp_downloaded = false; // Client variable
volatile bool g_prt_downloaded = false; // Client variable
volatile bool g_mightsee_downloaded = false; // Client variable
char* g_bsp_image = NULL; // Client/Server variable : Server uses it for cache for connecting clients, clients download it to memory to not require filesystem usage
char* g_prt_image = NULL; // Client/Server variable : Server uses it for cache for connecting clients, clients download it to memory to not require filesystem usage
unsigned long g_bsp_compressed_size = 0; // Server variable
unsigned long g_prt_compressed_size = 0; // Server variable
unsigned long g_bsp_size = 0; // Server variable
unsigned long g_prt_size = 0; // Server variable
#endif
#ifdef ZHLT_INFO_COMPILE_PARAMETERS
// AJM: addded in
// =====================================================================================
// GetParamsFromEnt
// this function is called from parseentity when it encounters the
// info_compile_parameters entity. each tool should have its own version of this
// to handle its own specific settings.
// =====================================================================================
void GetParamsFromEnt(entity_t* mapent)
{
int iTmp;
Log("\nCompile Settings detected from info_compile_parameters entity\n");
// verbose(choices) : "Verbose compile messages" : 0 = [ 0 : "Off" 1 : "On" ]
iTmp = IntForKey(mapent, "verbose");
if (iTmp == 1)
{
g_verbose = true;
}
else if (iTmp == 0)
{
g_verbose = false;
}
Log("%30s [ %-9s ]\n", "Compile Option", "setting");
Log("%30s [ %-9s ]\n", "Verbose Compile Messages", g_verbose ? "on" : "off");
// estimate(choices) :"Estimate Compile Times?" : 0 = [ 0: "Yes" 1: "No" ]
if (IntForKey(mapent, "estimate"))
{
g_estimate = true;
}
else
{
g_estimate = false;
}
Log("%30s [ %-9s ]\n", "Estimate Compile Times", g_estimate ? "on" : "off");
// priority(choices) : "Priority Level" : 0 = [ 0 : "Normal" 1 : "High" -1 : "Low" ]
if (!strcmp(ValueForKey(mapent, "priority"), "1"))
{
g_threadpriority = eThreadPriorityHigh;
Log("%30s [ %-9s ]\n", "Thread Priority", "high");
}
else if (!strcmp(ValueForKey(mapent, "priority"), "-1"))
{
g_threadpriority = eThreadPriorityLow;
Log("%30s [ %-9s ]\n", "Thread Priority", "low");
}
/*
hlvis(choices) : "HLVIS" : 2 =
[
0 : "Off"
1 : "Fast"
2 : "Normal"
3 : "Full"
]
*/
iTmp = IntForKey(mapent, "hlvis");
if (iTmp == 0)
{
Fatal(assume_TOOL_CANCEL,
"%s flag was not checked in info_compile_parameters entity, execution of %s cancelled", g_Program, g_Program);
CheckFatal();
}
else if (iTmp == 1)
{
g_fastvis = true;
g_fullvis = false;
}
else if (iTmp == 2)
{
g_fastvis = false;
g_fullvis = false;
}
else if (iTmp == 3)
{
g_fullvis = true;
g_fastvis = false;
}
Log("%30s [ %-9s ]\n", "Fast VIS", g_fastvis ? "on" : "off");
Log("%30s [ %-9s ]\n", "Full VIS", g_fullvis ? "on" : "off" );
///////////////////
Log("\n");
}
#endif
// =====================================================================================
// PlaneFromWinding
// =====================================================================================
static void PlaneFromWinding(winding_t* w, plane_t* plane)
{
vec3_t v1;
vec3_t v2;
// calc plane
VectorSubtract(w->points[2], w->points[1], v1);
VectorSubtract(w->points[0], w->points[1], v2);
CrossProduct(v2, v1, plane->normal);
VectorNormalize(plane->normal);
plane->dist = DotProduct(w->points[0], plane->normal);
}
// =====================================================================================
// NewWinding
// =====================================================================================
static winding_t* NewWinding(const int points)
{
winding_t* w;
int size;
if (points > MAX_POINTS_ON_WINDING)
{
Error("NewWinding: %i points > MAX_POINTS_ON_WINDING", points);
}
#ifdef ZHLT_64BIT_FIX
size = (int)(intptr_t)((winding_t*)0)->points[points];
#else
size = (int)((winding_t*)0)->points[points];
#endif
w = (winding_t*)calloc(1, size);
return w;
}
//=============================================================================
/////////
// NETVIS
#ifdef ZHLT_NETVIS
// =====================================================================================
// GetPortalPtr
// converts a portal index to a pointer
// =====================================================================================
portal_t* GetPortalPtr(const long index)
{
if (index < (g_numportals * 2))
{
return g_portals + index;
}
else
{
return (NULL);
}
}
// =====================================================================================
// GetNextPortalIndex
// This is called by ClientSockets
// =====================================================================================
int GetNextPortalIndex()
{
int j;
int best = NO_PORTAL_INDEX;
portal_t* p;
portal_t* tp;
int min;
ThreadLock();
min = 99999;
p = NULL;
for (j = 0, tp = g_portals; j < g_numportals * 2; j++, tp++)
{
if (tp->nummightsee < min && tp->status == stat_none)
{
min = tp->nummightsee;
p = tp;
best = j;
}
}
if (p)
{
p->status = stat_working;
}
else
{
best = NO_PORTAL_INDEX; // hack to return NO_PORTAL_INDEX to the queue'ing code
}
ThreadUnlock();
return best;
}
// =====================================================================================
// AllPortalsDone
// returns true if all portals are done...
// =====================================================================================
static int AllPortalsDone()
{
const unsigned numportals = g_numportals * 2;
portal_t* tp;
unsigned j;
for (j = 0, tp = g_portals; j < numportals; j++, tp++)
{
if (tp->status != stat_done)
{
return 0;
}
}
return 1;
}
#endif
// NETVIS
///////////
// =====================================================================================
// GetNextPortal
// Returns the next portal for a thread to work on
// Returns the portals from the least complex, so the later ones can reuse the earlier information.
// =====================================================================================
static portal_t* GetNextPortal()
{
int j;
portal_t* p;
portal_t* tp;
int min;
#ifdef ZHLT_NETVIS
if (g_vismode == VIS_MODE_SERVER)
{
#else
{
if (GetThreadWork() == -1)
{
return NULL;
}
#endif
ThreadLock();
min = 99999;
p = NULL;
for (j = 0, tp = g_portals; j < g_numportals * 2; j++, tp++)
{
if (tp->nummightsee < min && tp->status == stat_none)
{
min = tp->nummightsee;
p = tp;
#ifdef ZHLT_NETVIS
g_visportalindex = j;
#endif
}
}
if (p)
{
p->status = stat_working;
}
ThreadUnlock();
return p;
}
#ifdef ZHLT_NETVIS
else // AS CLIENT
{
while (getWorkFromClientQueue() == WAITING_FOR_PORTAL_INDEX)
{
unsigned delay = 100;
g_idletime += delay; // This is the only point where the portal work goes idle, so its easy to add up just how idle it is.
if (!isConnectedToServer())
{
Error("Unexepected disconnect from server(1)\n");
}
NetvisSleep(delay);
}
if (g_visportalindex == NO_PORTAL_INDEX)
{
g_visstate = VIS_CLIENT_DONE;
Send_VIS_GOING_DOWN(g_ClientSession);
return NULL;
}
// convert index to pointer
tp = GetPortalPtr(g_visportalindex);
if (tp)
{
tp->status = stat_working;
}
return (tp);
}
#endif
}
#ifdef HLVIS_MAXDIST
#ifndef ZHLT_DETAILBRUSH
// AJM: MVD
// =====================================================================================
// DecompressAll
// =====================================================================================
void DecompressAll(void)
{
int i;
byte *dest;
for(i = 0; i < g_portalleafs; i++)
{
dest = g_uncompressed + i * g_bitbytes;
DecompressVis((const unsigned char*)(g_dvisdata + (byte)g_dleafs[i + 1].visofs), dest, g_bitbytes);
}
}
// AJM: MVD
// =====================================================================================
// CompressAll
// =====================================================================================
void CompressAll(void)
{
int i, x = 0;
byte *dest;
byte *src;
byte compressed[MAX_MAP_LEAFS / 8];
vismap_p = vismap;
for(i = 0; i < g_portalleafs; i++)
{
memset(&compressed, 0, sizeof(compressed));
src = g_uncompressed + i * g_bitbytes;
// Compress all leafs into global compression buffer
x = CompressVis(src, g_bitbytes, compressed, sizeof(compressed));
dest = vismap_p;
vismap_p += x;
if (vismap_p > vismap_end)
{
Error("Vismap expansion overflow");
}
g_dleafs[i + 1].visofs = dest - vismap; // leaf 0 is a common solid
memcpy(dest, compressed, x);
}
}
#endif
#endif // HLVIS_MAXDIST
// =====================================================================================
// LeafThread
// =====================================================================================
#ifdef SYSTEM_WIN32
#pragma warning(push)
#pragma warning(disable: 4100) // unreferenced formal parameter
#endif
#ifndef ZHLT_NETVIS
static void LeafThread(int unused)
{
portal_t* p;
while (1)
{
if (!(p = GetNextPortal()))
{
return;
}
PortalFlow(p);
Verbose("portal:%4i mightsee:%4i cansee:%4i\n", (int)(p - g_portals), p->nummightsee, p->numcansee);
}
}
#endif //!ZHLT_NETVIS
#ifdef ZHLT_NETVIS
static void LeafThread(int unused)
{
if (g_vismode == VIS_MODE_CLIENT)
{
portal_t* p;
g_visstate = VIS_BASE_PORTAL_VIS_SERVER_WAIT;
Send_VIS_LEAFTHREAD(g_visleafs, g_visportals, g_bitbytes);
while (!g_visleafthread)
{
if (!isConnectedToServer())
{
Error("Unexepected disconnect from server(2)\n");
}
NetvisSleep(100);
}
g_visstate = VIS_PORTAL_FLOW;
Send_VIS_WANT_FULL_SYNC();
while (!g_NetvisAbort)
{
if (!(p = GetNextPortal()))
{
return;
}
PortalFlow(p);
Send_VIS_DONE_PORTAL(g_visportalindex, p);
g_vislocalportal++;
}
}
else if (g_vismode == VIS_MODE_SERVER)
{
#if 0
// Server does zero work in ZHLT netvis
g_visstate = VIS_WAIT_CLIENTS;
while (!g_NetvisAbort)
{
NetvisSleep(1000);
if (AllPortalsDone())
{
g_visstate = VIS_POST;
return;
}
}
#else
portal_t* p;
g_visstate = VIS_WAIT_CLIENTS;
while (!g_NetvisAbort)
{
if (!(p = GetNextPortal()))
{
if (AllPortalsDone())
{
g_visstate = VIS_POST;
return;
}
NetvisSleep(1000); // No need to churn while waiting on slow clients
continue;
}
PortalFlow(p);
g_vislocalportal++;
}
#endif
}
else
{
hlassume(false, assume_VALID_NETVIS_STATE);
}
}
#endif
#ifdef SYSTEM_WIN32
#pragma warning(pop)
#endif
// =====================================================================================
// LeafFlow
// Builds the entire visibility list for a leaf
// =====================================================================================
static void LeafFlow(const int leafnum)
{
leaf_t* leaf;
byte* outbuffer;
byte compressed[MAX_MAP_LEAFS / 8];
unsigned i;
unsigned j;
int k;
int tmp;
int numvis;
byte* dest;
portal_t* p;
//
// flow through all portals, collecting visible bits
//
memset(compressed, 0, sizeof(compressed));
outbuffer = g_uncompressed + leafnum * g_bitbytes;
leaf = &g_leafs[leafnum];
tmp = 0;
const unsigned offset = leafnum >> 3;
const unsigned bit = (1 << (leafnum & 7));
for (i = 0; i < leaf->numportals; i++)
{
p = leaf->portals[i];
if (p->status != stat_done)
{
Error("portal not done (leaf %d)", leafnum);
}
{
byte* dst = outbuffer;
byte* src = p->visbits;
for (j=0; j<g_bitbytes; j++, dst++, src++)
{
*dst |= *src;
}
}
if ((tmp == 0) && (outbuffer[offset] & bit))
{
tmp = 1;
Warning("Leaf portals saw into leaf");
Log(" Problem at portal between leaves %i and %i:\n ", leafnum, p->leaf);
for (k = 0; k < p->winding->numpoints; k++)
{
Log(" (%4.3f %4.3f %4.3f)\n", p->winding->points[k][0], p->winding->points[k][1], p->winding->points[k][2]);
}
Log("\n");
}
}
outbuffer[offset] |= bit;
#ifdef HLVIS_OVERVIEW
if (g_leafinfos[leafnum].isoverviewpoint)
{
for (i = 0; i < g_portalleafs; i++)
{
outbuffer[i >> 3] |= (1 << (i & 7));
}
}
#ifdef HLVIS_SKYBOXMODEL
for (i = 0; i < g_portalleafs; i++)
{
if (g_leafinfos[i].isskyboxpoint)
{
outbuffer[i >> 3] |= (1 << (i & 7));
}
}
#endif
#endif
numvis = 0;
for (i = 0; i < g_portalleafs; i++)
{
if (outbuffer[i >> 3] & (1 << (i & 7)))
{
numvis++;
}
}
//
// compress the bit string
//
Verbose("leaf %4i : %4i visible\n", leafnum, numvis);
totalvis += numvis;
#ifdef ZHLT_DETAILBRUSH
byte buffer2[MAX_MAP_LEAFS / 8];
int diskbytes = (g_leafcount_all + 7) >> 3;
memset (buffer2, 0, diskbytes);
for (i = 0; i < g_portalleafs; i++)
{
for (j = 0; j < g_leafcounts[i]; j++)
{
int srcofs = i >> 3;
int srcbit = 1 << (i & 7);
int dstofs = (g_leafstarts[i] + j) >> 3;
int dstbit = 1 << ((g_leafstarts[i] + j) & 7);
if (outbuffer[srcofs] & srcbit)
{
buffer2[dstofs] |= dstbit;
}
}
}
i = CompressVis (buffer2, diskbytes, compressed, sizeof (compressed));
#else
i = CompressVis(outbuffer, g_bitbytes, compressed, sizeof(compressed));
#endif
dest = vismap_p;
vismap_p += i;
if (vismap_p > vismap_end)
{
Error("Vismap expansion overflow");
}
#ifdef ZHLT_DETAILBRUSH
for (j = 0; j < g_leafcounts[leafnum]; j++)
{
g_dleafs[g_leafstarts[leafnum] + j + 1].visofs = dest - vismap;
}
#else
g_dleafs[leafnum + 1].visofs = dest - vismap; // leaf 0 is a common solid
#endif
memcpy(dest, compressed, i);
}
// =====================================================================================
// CalcPortalVis
// =====================================================================================
static void CalcPortalVis()
{
#ifndef ZHLT_NETVIS
// g_fastvis just uses mightsee for a very loose bound
if (g_fastvis)
{
int i;
for (i = 0; i < g_numportals * 2; i++)
{
g_portals[i].visbits = g_portals[i].mightsee;
g_portals[i].status = stat_done;
}
return;
}
#endif
#ifdef ZHLT_NETVIS
LeafThread(0);
#else
NamedRunThreadsOn(g_numportals * 2, g_estimate, LeafThread);
#endif
}
//////////////
// ZHLT_NETVIS
#ifdef ZHLT_NETVIS
// =====================================================================================
// CalcVis
// =====================================================================================
static void CalcVis()
{
unsigned lastpercent = 0;
int x, size;
if (g_vismode == VIS_MODE_SERVER)
{
g_visstate = VIS_BASE_PORTAL_VIS;
Log("BasePortalVis: \n");
for (x = 0, size = g_numportals * 2; x < size; x++)
{
unsigned percent = (x * 100 / size);
if (percent && (percent != lastpercent) && ((percent % 10) == 0))
{
lastpercent = percent;
#ifdef ZHLT_CONSOLE
PrintConsole
#else
printf
#endif
("%d%%....", percent);
}
BasePortalVis(x);
}
#ifdef ZHLT_CONSOLE
PrintConsole
#else
printf
#endif
("\n");
}
else
{
Send_VIS_WANT_MIGHTSEE_DATA();
while(!g_mightsee_downloaded)
{
if (!isConnectedToServer())
{
Error("Unexepected disconnect from server(3)\n");
}
NetvisSleep(100);
}
}
g_visportals = g_numportals;
g_visleafs = g_portalleafs;
g_starttime = I_FloatTime();
StartStatusDisplayThread(g_rate);
CalcPortalVis();
if (g_vismode == VIS_MODE_SERVER)
{
unsigned int i;
for (i = 0; i < g_portalleafs; i++)
{
LeafFlow(i);
}
Log("average leafs visible: %i\n", totalvis / g_portalleafs);
}
}
#endif
#ifndef ZHLT_NETVIS
#ifdef HLVIS_MAXDIST
#ifndef HLVIS_MAXDIST_NEW
// AJM: MVD
// =====================================================================================
// GetVisBlock
// =====================================================================================
visblocker_t *GetVisBlock(char *name)
{
int i;
visblocker_t *v;
for(i = 0, v = &g_visblockers[0]; i < g_numvisblockers; i++, v++)
{
if(!strcmp(name, v->name))
return v;
}
return NULL;
}
// AJM: MVD
// =====================================================================================
// InitVisBlock
// =====================================================================================
static void InitVisBlock(void)
{
char visfile[_MAX_PATH];
int i;
int x = 0;
int num_blocks;
int num_sides;
#ifdef ZHLT_DEFAULTEXTENSION_FIX
safe_snprintf(visfile, _MAX_PATH, "%s.vis", g_Mapname);
#else
strcpy(visfile, g_Mapname);
DefaultExtension(visfile, ".vis");
#endif
if(!q_exists(visfile))
return;
FILE *fp = fopen(visfile, "r");
if(!fp)
return;
while(!feof(fp))
{
fscanf(fp, "%s\n", g_visblockers[x].name);
fscanf(fp, "%d\n", &num_blocks);
for(i = 0; i < num_blocks; i++)
{
fscanf(fp, "%s\n", g_visblockers[x].blocknames[i]);
}
g_visblockers[x].numnames = num_blocks;
fscanf(fp, "%d\n", &num_sides);
for(i = 0; i < num_sides; i++)
{
fscanf(fp, "%f %f %f %f\n", &g_visblockers[x].planes[i].normal[0],
&g_visblockers[x].planes[i].normal[1],
&g_visblockers[x].planes[i].normal[2],
&g_visblockers[x].planes[i].dist);
}
g_visblockers[x].numplanes = num_sides;
g_visblockers[x].numleafs = 0;
x++;
}
g_numvisblockers = x;
}
// AJM: MVD
// =====================================================================================
// SetupVisBlockLeafs
// Set up the leafs for the visblocker
// =====================================================================================
static void SetupVisBlockLeafs(void)
{
int i, j, k, l, q;
visblocker_t *v;
leaf_t *leaf;
portal_t *p;
plane_t *plane;
float dist;
for(i = 0, v = &g_visblockers[0]; i < g_numvisblockers; i++, v++)
{
for(j = 0, leaf = &g_leafs[0]; j < g_portalleafs; j++, leaf++)
{
for(q = 0, p = leaf->portals[0]; q < leaf->numportals; q++, p++)
{
for(k = 0; k < p->winding->numpoints; k++)
{
for(l = 0, plane = &v->planes[0]; l < v->numplanes; l++, plane++)
{
dist = DotProduct(p->winding->points[k], plane->normal) - plane->dist;
if(dist > ON_EPSILON)
goto PostLoop;
}
}
}
PostLoop:
if(q != leaf->numportals)
continue;
// If we reach this point, then the portal is completely inside the visblocker
v->blockleafs[v->numleafs++] = j;
}
}
}
#endif
// AJM: MVD
// =====================================================================================
// SaveVisData
// =====================================================================================
void SaveVisData(const char *filename)
{
int i;
FILE *fp = fopen(filename, "wb");
if(!fp)
return;
SafeWrite(fp, g_dvisdata, (vismap_p - g_dvisdata));
// BUG BUG BUG!
// Leaf offsets need to be saved too!!!!
for(i = 0; i < g_numleafs; i++)
{
SafeWrite(fp, &g_dleafs[i].visofs, sizeof(int));
}
fclose(fp);
}
#ifndef HLVIS_MAXDIST_NEW
// AJM: MVD
// =====================================================================================
// ResetPortalStatus
// FIX: Used to reset p->status to stat_none; now it justs frees p->visbits
// =====================================================================================
void ResetPortalStatus(void)
{
int i;
portal_t* p = g_portals;
for(i = 0; i < g_numportals * 2; i++, p++)
{
//p->status = stat_none;
free(p->visbits);
}
}
#endif
#endif // HLVIS_MAXDIST
// AJM UNDONE HLVIS_MAXDIST THIS!!!!!!!!!!!!!
// AJM: MVD modified
// =====================================================================================
// CalcVis
// =====================================================================================
static void CalcVis()
{
unsigned i;
char visdatafile[_MAX_PATH];
#ifdef ZHLT_DEFAULTEXTENSION_FIX
safe_snprintf(visdatafile, _MAX_PATH, "%s.vdt", g_Mapname);
#else
strcpy(visdatafile, g_Mapname);
DefaultExtension(visdatafile, ".vdt");
#endif
// Remove this file
unlink(visdatafile);
/* if(g_postcompile)
{
if(!g_maxdistance)
{
Error("Must use -maxdistance parameter with -postcompile");
}
// Decompress everything so we can edit it
DecompressAll();
NamedRunThreadsOn(g_portalleafs, g_estimate, PostMaxDistVis);
// Recompress it
CompressAll();
}
else
{*/
// InitVisBlock();
// SetupVisBlockLeafs();
NamedRunThreadsOn(g_numportals * 2, g_estimate, BasePortalVis);
// if(g_numvisblockers)
// NamedRunThreadsOn(g_numvisblockers, g_estimate, BlockVis);
// First do a normal VIS, save to file, then redo MaxDistVis
CalcPortalVis();
//
// assemble the leaf vis lists by oring and compressing the portal lists
//
for (i = 0; i < g_portalleafs; i++)
{
LeafFlow(i);
}
Log("average leafs visible: %i\n", totalvis / g_portalleafs);
if(g_maxdistance)
{
totalvis = 0;
Log("saving visdata to %s...\n", visdatafile);
SaveVisData(visdatafile);
// We need to reset the uncompressed variable and portal visbits
free(g_uncompressed);
g_uncompressed = (byte*)calloc(g_portalleafs, g_bitbytes);
vismap_p = g_dvisdata;
// We don't need to run BasePortalVis again
NamedRunThreadsOn(g_portalleafs, g_estimate, MaxDistVis);
// No need to run this - MaxDistVis now writes directly to visbits after the initial VIS
//CalcPortalVis();
for (i = 0; i < g_portalleafs; i++)
{
LeafFlow(i);
}
#ifndef HLVIS_MAXDIST_NEW
// FIX: Used to reset p->status to stat_none; now it justs frees p->visbits
ResetPortalStatus();
#endif
Log("average maxdistance leafs visible: %i\n", totalvis / g_portalleafs);
}
// }
}
#endif //!ZHLT_NETVIS
// ZHLT_NETVIS
//////////////
// =====================================================================================
// CheckNullToken
// =====================================================================================
static INLINE void FASTCALL CheckNullToken(const char*const token)
{
if (token == NULL)
{
Error("LoadPortals: Damaged or invalid .prt file\n");
}
}
// =====================================================================================
// LoadPortals
// =====================================================================================
static void LoadPortals(char* portal_image)
{
int i, j;
portal_t* p;
leaf_t* l;
int numpoints;
winding_t* w;
int leafnums[2];
plane_t plane;
const char* const seperators = " ()\r\n\t";
char* token;
token = strtok(portal_image, seperators);
CheckNullToken(token);
if (!sscanf(token, "%u", &g_portalleafs))
{
Error("LoadPortals: failed to read header: number of leafs");
}
token = strtok(NULL, seperators);
CheckNullToken(token);
if (!sscanf(token, "%i", &g_numportals))
{
Error("LoadPortals: failed to read header: number of portals");
}
Log("%4i portalleafs\n", g_portalleafs);
Log("%4i numportals\n", g_numportals);
g_bitbytes = ((g_portalleafs + 63) & ~63) >> 3;
g_bitlongs = g_bitbytes / sizeof(long);
// each file portal is split into two memory portals
g_portals = (portal_t*)calloc(2 * g_numportals, sizeof(portal_t));
g_leafs = (leaf_t*)calloc(g_portalleafs, sizeof(leaf_t));
#ifdef HLVIS_OVERVIEW
g_leafinfos = (leafinfo_t*)calloc(g_portalleafs, sizeof(leafinfo_t));
#endif
#ifdef ZHLT_DETAILBRUSH
g_leafcounts = (int*)calloc(g_portalleafs, sizeof(int));
g_leafstarts = (int*)calloc(g_portalleafs, sizeof(int));
#endif
originalvismapsize = g_portalleafs * ((g_portalleafs + 7) / 8);
vismap = vismap_p = g_dvisdata;
vismap_end = vismap + MAX_MAP_VISIBILITY;
#ifdef ZHLT_DETAILBRUSH
if (g_portalleafs > MAX_MAP_LEAFS)
{ // this may cause hlvis to overflow, because numportalleafs can be larger than g_numleafs in some special cases
Error ("Too many portalleafs (g_portalleafs(%d) > MAX_MAP_LEAFS(%d)).", g_portalleafs, MAX_MAP_LEAFS);
}
g_leafcount_all = 0;
for (i = 0; i < g_portalleafs; i++)
{
unsigned rval = 0;
token = strtok(NULL, seperators);
CheckNullToken(token);
rval += sscanf(token, "%i", &g_leafcounts[i]);
if (rval != 1)
{
Error("LoadPortals: read leaf %i failed", i);
}
g_leafstarts[i] = g_leafcount_all;
g_leafcount_all += g_leafcounts[i];
}
if (g_leafcount_all != g_dmodels[0].visleafs)
{ // internal error (this should never happen)
Error ("Corrupted leaf mapping (g_leafcount_all(%d) != g_dmodels[0].visleafs(%d)).", g_leafcount_all, g_dmodels[0].visleafs);
}
#endif
#ifdef HLVIS_OVERVIEW
for (i = 0; i < g_portalleafs; i++)
{
for (j = 0; j < g_overview_count; j++)
{
#ifdef ZHLT_DETAILBRUSH
int d = g_overview[j].visleafnum - g_leafstarts[i];
if (0 <= d && d < g_leafcounts[i])
#else
if (g_overview[j].visleafnum == i)
#endif
{
#ifdef HLVIS_SKYBOXMODEL
if (g_overview[j].reverse)
{
g_leafinfos[i].isskyboxpoint = true;
}
else
{
g_leafinfos[i].isoverviewpoint = true;
}
#else
g_leafinfos[i].isoverviewpoint = true;
#endif
}
}
}
#endif
for (i = 0, p = g_portals; i < g_numportals; i++)
{
unsigned rval = 0;
token = strtok(NULL, seperators);
CheckNullToken(token);
rval += sscanf(token, "%i", &numpoints);
token = strtok(NULL, seperators);
CheckNullToken(token);
rval += sscanf(token, "%i", &leafnums[0]);
token = strtok(NULL, seperators);
CheckNullToken(token);
rval += sscanf(token, "%i", &leafnums[1]);
if (rval != 3)
{
Error("LoadPortals: reading portal %i", i);
}
if (numpoints > MAX_POINTS_ON_WINDING)
{
Error("LoadPortals: portal %i has too many points", i);
}
if (((unsigned)leafnums[0] > g_portalleafs) || ((unsigned)leafnums[1] > g_portalleafs))
{
Error("LoadPortals: reading portal %i", i);
}
w = p->winding = NewWinding(numpoints);
w->original = true;
w->numpoints = numpoints;
for (j = 0; j < numpoints; j++)
{
int k;
double v[3];
unsigned rval = 0;
token = strtok(NULL, seperators);
CheckNullToken(token);
rval += sscanf(token, "%lf", &v[0]);
token = strtok(NULL, seperators);
CheckNullToken(token);
rval += sscanf(token, "%lf", &v[1]);
token = strtok(NULL, seperators);
CheckNullToken(token);
rval += sscanf(token, "%lf", &v[2]);
// scanf into double, then assign to vec_t
if (rval != 3)
{
Error("LoadPortals: reading portal %i", i);
}
for (k = 0; k < 3; k++)
{
w->points[j][k] = v[k];
}
}
// calc plane
PlaneFromWinding(w, &plane);
// create forward portal
l = &g_leafs[leafnums[0]];
hlassume(l->numportals < MAX_PORTALS_ON_LEAF, assume_MAX_PORTALS_ON_LEAF);
l->portals[l->numportals] = p;
l->numportals++;
p->winding = w;
VectorSubtract(vec3_origin, plane.normal, p->plane.normal);
p->plane.dist = -plane.dist;
p->leaf = leafnums[1];
p++;
// create backwards portal
l = &g_leafs[leafnums[1]];
hlassume(l->numportals < MAX_PORTALS_ON_LEAF, assume_MAX_PORTALS_ON_LEAF);
l->portals[l->numportals] = p;
l->numportals++;
p->winding = NewWinding(w->numpoints);
p->winding->numpoints = w->numpoints;
for (j = 0; j < w->numpoints; j++)
{
VectorCopy(w->points[w->numpoints - 1 - j], p->winding->points[j]);
}
p->plane = plane;
p->leaf = leafnums[0];
p++;
}
}
// =====================================================================================
// LoadPortalsByFilename
// =====================================================================================
static void LoadPortalsByFilename(const char* const filename)
{
char* file_image;
if (!q_exists(filename))
{
Error("Portal file '%s' does not exist, cannot vis the map\n", filename);
}
LoadFile(filename, &file_image);
LoadPortals(file_image);
free(file_image);
}
#if ZHLT_ZONES
// =====================================================================================
// AssignPortalsToZones
// =====================================================================================
static void AssignPortalsToZones()
{
hlassert(g_Zones != NULL);
UINT32 count = 0;
portal_t* p;
UINT32 x;
UINT32 tmp[20];
memset(tmp, 0, sizeof(tmp));
UINT32 numportals = g_numportals * 2;
for (x=0, p=g_portals; x<numportals; x++, p++)
{
BoundingBox bounds;
winding_t* w = p->winding;
UINT32 numpoints = w->numpoints;
UINT32 y;
for (y=0; y<numpoints; y++)
{
bounds.add(w->points[y]);
}
p->zone = g_Zones->getZoneFromBounds(bounds);
tmp[p->zone]++;
if (p->zone)
{
count++;
}
}
for (x=0; x<15; x++)
{
Log("Zone %2u : %u\n", x, tmp[x]);
}
Log("%u of %u portals were contained in func_vis zones\n", count, numportals);
}
#endif
// =====================================================================================
// Usage
// =====================================================================================
static void Usage()
{
Banner();
Log("\n-= %s Options =-\n\n", g_Program);
#ifdef ZHLT_CONSOLE
Log(" -console # : Set to 0 to turn off the pop-up console (default is 1)\n");
#endif
#ifdef ZHLT_LANGFILE
Log(" -lang file : localization file\n");
#endif
Log(" -full : Full vis\n");
Log(" -fast : Fast vis\n\n");
#ifdef ZHLT_NETVIS
Log(" -connect address : Connect to netvis server at address as a client\n");
Log(" -server : Run as the netvis server\n");
Log(" -port # : Use a non-standard port for netvis\n");
Log(" -rate # : Alter the display update rate\n\n");
#endif
Log(" -texdata # : Alter maximum texture memory limit (in kb)\n");
Log(" -lightdata # : Alter maximum lighting memory limit (in kb)\n"); //lightdata //--vluzacn
Log(" -chart : display bsp statitics\n");
Log(" -low | -high : run program an altered priority level\n");
Log(" -nolog : don't generate the compile logfiles\n");
Log(" -threads # : manually specify the number of threads to run\n");
#ifdef SYSTEM_WIN32
Log(" -estimate : display estimated time during compile\n");
#endif
#ifdef ZHLT_PROGRESSFILE // AJM
Log(" -progressfile path : specify the path to a file for progress estimate output\n");
#endif
#ifdef SYSTEM_POSIX
Log(" -noestimate : do not display continuous compile time estimates\n");
#endif
#ifdef HLVIS_MAXDIST // AJM: MVD
Log(" -maxdistance # : Alter the maximum distance for visibility\n");
#endif
Log(" -verbose : compile with verbose messages\n");
Log(" -noinfo : Do not show tool configuration information\n");
Log(" -dev # : compile with developer message\n\n");
Log(" mapfile : The mapfile to compile\n\n");
#ifdef ZHLT_NETVIS
Log("\n"
"In netvis one computer must be the server and all the rest are the clients.\n"
"The server should be started with : netvis -server mapname\n"
"And the clients should be started with : netvis -connect servername\n"
"\n"
"The default socket it uses is 21212 and can be changed with -port\n"
"The default update rate is 60 seconds and can be changed with -rate\n");
#endif
exit(1);
}
// =====================================================================================
// Settings
// =====================================================================================
static void Settings()
{
char* tmp;
if (!g_info)
{
return;
}
Log("\n-= Current %s Settings =-\n", g_Program);
Log("Name | Setting | Default\n" "-------------------|-----------|-------------------------\n");
// ZHLT Common Settings
if (DEFAULT_NUMTHREADS == -1)
{
Log("threads [ %7d ] [ Varies ]\n", g_numthreads);
}
else
{
Log("threads [ %7d ] [ %7d ]\n", g_numthreads, DEFAULT_NUMTHREADS);
}
Log("verbose [ %7s ] [ %7s ]\n", g_verbose ? "on" : "off", DEFAULT_VERBOSE ? "on" : "off");
Log("log [ %7s ] [ %7s ]\n", g_log ? "on" : "off", DEFAULT_LOG ? "on" : "off");
Log("developer [ %7d ] [ %7d ]\n", g_developer, DEFAULT_DEVELOPER);
Log("chart [ %7s ] [ %7s ]\n", g_chart ? "on" : "off", DEFAULT_CHART ? "on" : "off");
Log("estimate [ %7s ] [ %7s ]\n", g_estimate ? "on" : "off", DEFAULT_ESTIMATE ? "on" : "off");
Log("max texture memory [ %7d ] [ %7d ]\n", g_max_map_miptex, DEFAULT_MAX_MAP_MIPTEX);
#ifdef HLVIS_MAXDIST // AJM: MVD
Log("max vis distance [ %7d ] [ %7d ]\n", g_maxdistance, DEFAULT_MAXDISTANCE_RANGE);
//Log("max dist only [ %7s ] [ %7s ]\n", g_postcompile ? "on" : "off", DEFAULT_POST_COMPILE ? "on" : "off");
#endif
switch (g_threadpriority)
{
case eThreadPriorityNormal:
default:
tmp = "Normal";
break;
case eThreadPriorityLow:
tmp = "Low";
break;
case eThreadPriorityHigh:
tmp = "High";
break;
}
Log("priority [ %7s ] [ %7s ]\n", tmp, "Normal");
Log("\n");
// HLVIS Specific Settings
Log("fast vis [ %7s ] [ %7s ]\n", g_fastvis ? "on" : "off", DEFAULT_FASTVIS ? "on" : "off");
Log("full vis [ %7s ] [ %7s ]\n", g_fullvis ? "on" : "off", DEFAULT_FULLVIS ? "on" : "off");
#ifdef ZHLT_NETVIS
if (g_vismode == VIS_MODE_SERVER)
{
Log("netvis mode [ Server ]\n");
}
else if (g_vismode == VIS_MODE_CLIENT)
{
Log("netvis mode [ Client, connected to %s ]\n", g_server_addr);
}
Log("netvis port [ %7d ] [ %7d ]\n", g_port, DEFAULT_NETVIS_PORT);
Log("netvis display rate [ %7d ] [ %7d ]\n", g_rate, DEFAULT_NETVIS_RATE);
#endif
Log("\n\n");
}
#ifdef HLVIS_OVERVIEW
int VisLeafnumForPoint(const vec3_t point)
{
int nodenum;
vec_t dist;
dnode_t* node;
dplane_t* plane;
nodenum = 0;
while (nodenum >= 0)
{
node = &g_dnodes[nodenum];
plane = &g_dplanes[node->planenum];
dist = DotProduct(point, plane->normal) - plane->dist;
if (dist >= 0.0)
{
nodenum = node->children[0];
}
else
{
nodenum = node->children[1];
}
}
return -nodenum - 2;
}
#endif
// =====================================================================================
// main
// =====================================================================================
int main(const int argc, char** argv)
{
char portalfile[_MAX_PATH];
char source[_MAX_PATH];
int i;
double start, end;
const char* mapname_from_arg = NULL;
#ifdef ZHLT_NETVIS
g_Program = "netvis";
#else
g_Program = "hlvis";
#endif
#ifdef ZHLT_PARAMFILE
int argcold = argc;
char ** argvold = argv;
{
int argc;
char ** argv;
ParseParamFile (argcold, argvold, argc, argv);
{
#endif
#ifdef ZHLT_CONSOLE
if (InitConsole (argc, argv) < 0)
Usage();
#endif
if (argc == 1)
{
Usage();
}
for (i = 1; i < argc; i++)
{
if (!strcasecmp(argv[i], "-threads"))
{
if (i + 1 < argc) //added "1" .--vluzacn
{
g_numthreads = atoi(argv[++i]);
if (g_numthreads < 1)
{
Log("Expected value of at least 1 for '-threads'\n");
Usage();
}
}
else
{
Usage();
}
}
#ifdef ZHLT_CONSOLE
else if (!strcasecmp(argv[i], "-console"))
{
#ifndef SYSTEM_WIN32
Warning("The option '-console #' is only valid for Windows.");
#endif
if (i + 1 < argc)
++i;
else
Usage();
}
#endif
#ifdef SYSTEM_WIN32
else if (!strcasecmp(argv[i], "-estimate"))
{
g_estimate = true;
}
#endif
#ifdef SYSTEM_POSIX
else if (!strcasecmp(argv[i], "-noestimate"))
{
g_estimate = false;
}
#endif
#ifdef ZHLT_NETVIS
else if (!strcasecmp(argv[i], "-server"))
{
g_vismode = VIS_MODE_SERVER;
}
else if (!strcasecmp(argv[i], "-connect"))
{
if (i + 1 < argc) //added "1" .--vluzacn
{
g_vismode = VIS_MODE_CLIENT;
g_server_addr = argv[++i];
}
else
{
Usage();
}
}
else if (!strcasecmp(argv[i], "-port"))
{
if (i + 1 < argc) //added "1" .--vluzacn
{
g_port = atoi(argv[++i]);
}
else
{
Usage();
}
}
else if (!strcasecmp(argv[i], "-rate"))
{
if (i + 1 < argc) //added "1" .--vluzacn
{
g_rate = atoi(argv[++i]);
}
else
{
Usage();
}
if (g_rate < 5)
{
Log("Minimum -rate is 5, setting to 5 seconds\n");
g_rate = 5;
}
if (g_rate > 900)
{
Log("Maximum -rate is 900, setting to 900 seconds\n");
g_rate = 900;
}
}
#endif
#ifndef ZHLT_NETVIS
else if (!strcasecmp(argv[i], "-fast"))
{
Log("g_fastvis = true\n");
g_fastvis = true;
}
#endif
else if (!strcasecmp(argv[i], "-full"))
{
g_fullvis = true;
}
else if (!strcasecmp(argv[i], "-dev"))
{
if (i + 1 < argc) //added "1" .--vluzacn
{
g_developer = (developer_level_t)atoi(argv[++i]);
}
else
{
Usage();
}
}
else if (!strcasecmp(argv[i], "-verbose"))
{
g_verbose = true;
}
else if (!strcasecmp(argv[i], "-noinfo"))
{
g_info = false;
}
else if (!strcasecmp(argv[i], "-chart"))
{
g_chart = true;
}
else if (!strcasecmp(argv[i], "-low"))
{
g_threadpriority = eThreadPriorityLow;
}
else if (!strcasecmp(argv[i], "-high"))
{
g_threadpriority = eThreadPriorityHigh;
}
else if (!strcasecmp(argv[i], "-nolog"))
{
g_log = false;
}
else if (!strcasecmp(argv[i], "-texdata"))
{
if (i + 1 < argc) //added "1" .--vluzacn
{
int x = atoi(argv[++i]) * 1024;
//if (x > g_max_map_miptex) //--vluzacn
{
g_max_map_miptex = x;
}
}
else
{
Usage();
}
}
else if (!strcasecmp(argv[i], "-lightdata")) //lightdata
{
if (i + 1 < argc) //--vluzacn
{
int x = atoi(argv[++i]) * 1024;
//if (x > g_max_map_lightdata) //--vluzacn
{
g_max_map_lightdata = x; //--vluzacn
}
}
else
{
Usage();
}
}
#ifdef ZHLT_PROGRESSFILE // AJM
else if (!strcasecmp(argv[i], "-progressfile"))
{
if (i + 1 < argc) //added "1" .--vluzacn
{
g_progressfile = argv[++i];
}
else
{
Log("Error: -progressfile: expected path to progress file following parameter\n");
Usage();
}
}
#endif
#ifdef HLVIS_MAXDIST
// AJM: MVD
else if(!strcasecmp(argv[i], "-maxdistance"))
{
if(i + 1 < argc) //added "1" .--vluzacn
{
g_maxdistance = abs(atoi(argv[++i]));
}
else
{
Usage();
}
}
/* else if(!strcasecmp(argv[i], "-postcompile"))
{
g_postcompile = true;
}*/
#endif
#ifdef ZHLT_LANGFILE
else if (!strcasecmp (argv[i], "-lang"))
{
if (i + 1 < argc)
{
char tmp[_MAX_PATH];
#ifdef SYSTEM_WIN32
GetModuleFileName (NULL, tmp, _MAX_PATH);
#else
safe_strncpy (tmp, argv[0], _MAX_PATH);
#endif
LoadLangFile (argv[++i], tmp);
}
else
{
Usage();
}
}
#endif
else if (argv[i][0] == '-')
{
Log("Unknown option \"%s\"", argv[i]);
Usage();
}
else if (!mapname_from_arg)
{
mapname_from_arg = argv[i];
}
else
{
Log("Unknown option \"%s\"\n", argv[i]);
Usage();
}
}
#ifdef ZHLT_NETVIS
threads_InitCrit();
if (g_vismode == VIS_MODE_CLIENT)
{
ConnectToServer(g_server_addr, g_port);
while (!isConnectedToServer())
{
NetvisSleep(100);
}
Send_VIS_LOGIN();
while (!g_clientid)
{
if (!isConnectedToServer())
{
Error("Unexepected disconnect from server(4)\n");
}
NetvisSleep(100);
}
mapname_from_arg = "proxy";
}
else if (g_vismode == VIS_MODE_SERVER)
{
StartNetvisSocketServer(g_port);
if (!mapname_from_arg)
{
Log("No mapfile specified\n");
Usage();
}
}
else
{
Log("Netvis must be run either as a server (-server)\n" "or as a client (-connect servername)\n\n");
Usage();
}
#else
if (!mapname_from_arg)
{
Log("No mapfile specified\n");
Usage();
}
#endif
#ifdef ZHLT_NETVIS
if (g_vismode == VIS_MODE_CLIENT)
{
g_log = false;
}
#endif
safe_strncpy(g_Mapname, mapname_from_arg, _MAX_PATH);
FlipSlashes(g_Mapname);
StripExtension(g_Mapname);
OpenLog(g_clientid);
atexit(CloseLog);
ThreadSetDefault();
ThreadSetPriority(g_threadpriority);
#ifdef ZHLT_PARAMFILE
LogStart(argcold, argvold);
{
int i;
Log("Arguments: ");
for (i = 1; i < argc; i++)
{
if (strchr(argv[i], ' '))
{
Log("\"%s\" ", argv[i]);
}
else
{
Log("%s ", argv[i]);
}
}
Log("\n");
}
#else
LogStart(argc, argv);
#endif
#ifdef ZHLT_NETVIS
if (g_vismode == VIS_MODE_CLIENT)
{
Log("ZHLT NETVIS Client #%d\n", g_clientid);
g_log = false;
}
else
{
Log("ZHLT NETVIS Server\n");
}
#endif
CheckForErrorLog();
#ifdef ZHLT_64BIT_FIX
#ifdef PLATFORM_CAN_CALC_EXTENT
hlassume (CalcFaceExtents_test (), assume_first);
#endif
#endif
dtexdata_init();
atexit(dtexdata_free);
// END INIT
// BEGIN VIS
start = I_FloatTime();
safe_strncpy(source, g_Mapname, _MAX_PATH);
safe_strncat(source, ".bsp", _MAX_PATH);
safe_strncpy(portalfile, g_Mapname, _MAX_PATH);
safe_strncat(portalfile, ".prt", _MAX_PATH);
#ifdef ZHLT_NETVIS
if (g_vismode == VIS_MODE_SERVER)
{
LoadBSPFile(source);
LoadPortalsByFilename(portalfile);
char* bsp_image;
char* prt_image;
g_bsp_size = LoadFile(source, &bsp_image);
g_prt_size = LoadFile(portalfile, &prt_image);
g_bsp_compressed_size = (g_bsp_size * 1.01) + 12; // Magic numbers come from zlib documentation
g_prt_compressed_size = (g_prt_size * 1.01) + 12; // Magic numbers come from zlib documentation
char* bsp_compressed_image = (char*)malloc(g_bsp_compressed_size);
char* prt_compressed_image = (char*)malloc(g_prt_compressed_size);
int rval;
rval = compress2((byte*)bsp_compressed_image, &g_bsp_compressed_size, (byte*)bsp_image, g_bsp_size, 5);
if (rval != Z_OK)
{
Error("zlib Compression error with bsp image\n");
}
rval = compress2((byte*)prt_compressed_image, &g_prt_compressed_size, (byte*)prt_image, g_prt_size, 7);
if (rval != Z_OK)
{
Error("zlib Compression error with prt image\n");
}
free(bsp_image);
free(prt_image);
g_bsp_image = bsp_compressed_image;
g_prt_image = prt_compressed_image;
}
else if (g_vismode == VIS_MODE_CLIENT)
{
Send_VIS_WANT_BSP_DATA();
while (!g_bsp_downloaded)
{
if (!isConnectedToServer())
{
Error("Unexepected disconnect from server(5)\n");
}
NetvisSleep(100);
}
Send_VIS_WANT_PRT_DATA();
while (!g_prt_downloaded)
{
if (!isConnectedToServer())
{
Error("Unexepected disconnect from server(6)\n");
}
NetvisSleep(100);
}
LoadPortals(g_prt_image);
free(g_prt_image);
}
#else // NOT ZHLT_NETVIS
LoadBSPFile(source);
ParseEntities();
#ifdef HLVIS_OVERVIEW
{
int i;
for (i = 0; i < g_numentities; i++)
{
if (!strcmp (ValueForKey (&g_entities[i], "classname"), "info_overview_point"))
{
if (g_overview_count < g_overview_max)
{
vec3_t p;
GetVectorForKey (&g_entities[i], "origin", p);
VectorCopy (p, g_overview[g_overview_count].origin);
g_overview[g_overview_count].visleafnum = VisLeafnumForPoint (p);
#ifdef HLVIS_SKYBOXMODEL
g_overview[g_overview_count].reverse = IntForKey (&g_entities[i], "reverse");
#endif
g_overview_count++;
}
}
}
}
#endif
LoadPortalsByFilename(portalfile);
# if ZHLT_ZONES
g_Zones = MakeZones();
AssignPortalsToZones();
# endif
#endif
Settings();
g_uncompressed = (byte*)calloc(g_portalleafs, g_bitbytes);
CalcVis();
#ifdef ZHLT_NETVIS
if (g_vismode == VIS_MODE_SERVER)
{
g_visdatasize = vismap_p - g_dvisdata;
Log("g_visdatasize:%i compressed from %i\n", g_visdatasize, originalvismapsize);
if (g_chart)
{
PrintBSPFileSizes();
}
WriteBSPFile(source);
end = I_FloatTime();
LogTimeElapsed(end - start);
free(g_uncompressed);
// END VIS
#ifndef SYSTEM_WIN32
// Talk about cheese . . .
StopNetvisSocketServer();
#endif
}
else if (g_vismode == VIS_MODE_CLIENT)
{
#ifndef SYSTEM_WIN32
// Dont ask . .
DisconnectFromServer();
#endif
end = I_FloatTime();
LogTimeElapsed(end - start);
free(g_uncompressed);
// END VIS
}
threads_UninitCrit();
#else // NOT ZHLT_NETVIS
g_visdatasize = vismap_p - g_dvisdata;
Log("g_visdatasize:%i compressed from %i\n", g_visdatasize, originalvismapsize);
if (g_chart)
{
PrintBSPFileSizes();
}
WriteBSPFile(source);
end = I_FloatTime();
LogTimeElapsed(end - start);
free(g_uncompressed);
// END VIS
#endif // ZHLT_NETVIS
#ifdef ZHLT_PARAMFILE
}
}
#endif
return 0;
}