mirror of
https://github.com/nzp-team/vhlt.git
synced 2024-11-24 21:02:22 +00:00
944 lines
23 KiB
C++
944 lines
23 KiB
C++
#include "qrad.h"
|
|
|
|
#ifndef HLRAD_TRANSPARENCY_CPP
|
|
// Transparency array
|
|
|
|
#ifdef HLRAD_HULLU
|
|
|
|
typedef struct {
|
|
unsigned x;
|
|
unsigned y;
|
|
vec3_t transparency;
|
|
} transparency_t;
|
|
static transparency_t *s_transparency_list=NULL;
|
|
static unsigned long s_transparency_count=0;
|
|
static unsigned long s_max_transparency_count=0;
|
|
|
|
static void FindOpacity(const unsigned p1, const unsigned p2, vec3_t &out)
|
|
{
|
|
for(unsigned long i = 0; i < s_transparency_count; i++)
|
|
{
|
|
if(s_transparency_list[i].x==p1 && s_transparency_list[i].y==p2)
|
|
{
|
|
VectorCopy(s_transparency_list[i].transparency, out);
|
|
return;
|
|
}
|
|
}
|
|
VectorFill(out, 1.0);
|
|
}
|
|
|
|
#endif /*HLRAD_HULLU*/
|
|
#endif
|
|
|
|
|
|
typedef struct
|
|
{
|
|
unsigned offset:24;
|
|
unsigned values:8;
|
|
}
|
|
sparse_row_t;
|
|
|
|
typedef struct
|
|
{
|
|
sparse_row_t* row;
|
|
int count;
|
|
}
|
|
sparse_column_t;
|
|
|
|
sparse_column_t* s_vismatrix;
|
|
|
|
// Vismatrix protected
|
|
static unsigned IsVisbitInArray(const unsigned x, const unsigned y)
|
|
{
|
|
int first, last, current;
|
|
int y_byte = y / 8;
|
|
sparse_row_t* row;
|
|
sparse_column_t* column = s_vismatrix + x;
|
|
|
|
if (!column->count)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
first = 0;
|
|
last = column->count - 1;
|
|
|
|
// Warning("Searching . . .");
|
|
// binary search to find visbit
|
|
while (1)
|
|
{
|
|
current = (first + last) / 2;
|
|
row = column->row + current;
|
|
// Warning("first %u, last %u, current %u, row %p, row->offset %u", first, last, current, row, row->offset);
|
|
if ((row->offset) < y_byte)
|
|
{
|
|
first = current + 1;
|
|
}
|
|
else if ((row->offset) > y_byte)
|
|
{
|
|
last = current - 1;
|
|
}
|
|
else
|
|
{
|
|
return current;
|
|
}
|
|
if (first > last)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
static void SetVisColumn (int patchnum, bool uncompressedcolumn[MAX_SPARSE_VISMATRIX_PATCHES])
|
|
{
|
|
sparse_column_t *column;
|
|
int mbegin;
|
|
int m;
|
|
int i;
|
|
unsigned int bits;
|
|
|
|
column = &s_vismatrix[patchnum];
|
|
if (column->count || column->row)
|
|
{
|
|
Error ("SetVisColumn: column has been set");
|
|
}
|
|
|
|
for (mbegin = 0; mbegin < g_num_patches; mbegin += 8)
|
|
{
|
|
bits = 0;
|
|
for (m = mbegin; m < mbegin + 8; m++)
|
|
{
|
|
if (m >= g_num_patches)
|
|
{
|
|
break;
|
|
}
|
|
if (uncompressedcolumn[m]) // visible
|
|
{
|
|
if (m < patchnum)
|
|
{
|
|
Error ("SetVisColumn: invalid parameter: m < patchnum");
|
|
}
|
|
bits |= (1 << (m - mbegin));
|
|
}
|
|
}
|
|
if (bits)
|
|
{
|
|
column->count++;
|
|
}
|
|
}
|
|
|
|
if (!column->count)
|
|
{
|
|
return;
|
|
}
|
|
column->row = (sparse_row_t *)malloc (column->count * sizeof (sparse_row_t));
|
|
hlassume (column->row != NULL, assume_NoMemory);
|
|
|
|
i = 0;
|
|
for (mbegin = 0; mbegin < g_num_patches; mbegin += 8)
|
|
{
|
|
bits = 0;
|
|
for (m = mbegin; m < mbegin + 8; m++)
|
|
{
|
|
if (m >= g_num_patches)
|
|
{
|
|
break;
|
|
}
|
|
if (uncompressedcolumn[m]) // visible
|
|
{
|
|
bits |= (1 << (m - mbegin));
|
|
}
|
|
}
|
|
if (bits)
|
|
{
|
|
column->row[i].offset = mbegin / 8;
|
|
column->row[i].values = bits;
|
|
i++;
|
|
}
|
|
}
|
|
if (i != column->count)
|
|
{
|
|
Error ("SetVisColumn: internal error");
|
|
}
|
|
}
|
|
#else
|
|
// Vismatrix protected
|
|
static void InsertVisbitIntoArray(const unsigned x, const unsigned y)
|
|
{
|
|
unsigned count;
|
|
unsigned y_byte = y / 8;
|
|
sparse_column_t* column = s_vismatrix + x;
|
|
sparse_row_t* row = column->row;
|
|
|
|
if (!column->count)
|
|
{
|
|
column->count++;
|
|
row = column->row = (sparse_row_t*)malloc(sizeof(sparse_row_t));
|
|
#ifdef HLRAD_HLASSUMENOMEMORY
|
|
hlassume (row != NULL, assume_NoMemory);
|
|
#endif
|
|
row->offset = y_byte;
|
|
row->values = 1 << (y & 7);
|
|
return;
|
|
}
|
|
|
|
// Insertion
|
|
count = 0;
|
|
while (count < column->count)
|
|
{
|
|
if (row->offset > y_byte)
|
|
{
|
|
unsigned newsize = (column->count + 1) * sizeof(sparse_row_t);
|
|
sparse_row_t* newrow = (sparse_row_t*)malloc(newsize);
|
|
#ifdef HLRAD_HLASSUMENOMEMORY
|
|
hlassume (newrow != NULL, assume_NoMemory);
|
|
#endif
|
|
|
|
memcpy(newrow, column->row, count * sizeof(sparse_row_t));
|
|
memcpy(newrow + count + 1, column->row + count, (column->count - count) * sizeof(sparse_row_t));
|
|
|
|
row = newrow + count;
|
|
row->offset = y_byte;
|
|
row->values = 1 << (y & 7);
|
|
|
|
free(column->row);
|
|
column->row = newrow;
|
|
column->count++;
|
|
return;
|
|
}
|
|
|
|
row++;
|
|
count++;
|
|
}
|
|
|
|
// Append
|
|
{
|
|
unsigned newsize = (count + 1) * sizeof(sparse_row_t);
|
|
sparse_row_t* newrow = (sparse_row_t*)malloc(newsize);
|
|
#ifdef HLRAD_HLASSUMENOMEMORY
|
|
hlassume (newrow != NULL, assume_NoMemory);
|
|
#endif
|
|
|
|
memcpy(newrow, column->row, column->count * sizeof(sparse_row_t));
|
|
|
|
row = newrow + column->count;
|
|
row->offset = y_byte;
|
|
row->values = 1 << (y & 7);
|
|
|
|
free(column->row);
|
|
column->row = newrow;
|
|
column->count++;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Vismatrix public
|
|
static void SetVisBit(unsigned x, unsigned y)
|
|
{
|
|
unsigned offset;
|
|
|
|
if (x == y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (x > y)
|
|
{
|
|
const unsigned a = x;
|
|
const unsigned b = y;
|
|
x = b;
|
|
y = a;
|
|
}
|
|
|
|
if (x > g_num_patches)
|
|
{
|
|
Warning("in SetVisBit(), x > num_patches");
|
|
}
|
|
if (y > g_num_patches)
|
|
{
|
|
Warning("in SetVisBit(), y > num_patches");
|
|
}
|
|
|
|
ThreadLock();
|
|
|
|
if ((offset = IsVisbitInArray(x, y)) != -1)
|
|
{
|
|
s_vismatrix[x].row[offset].values |= 1 << (y & 7);
|
|
}
|
|
else
|
|
{
|
|
InsertVisbitIntoArray(x, y);
|
|
}
|
|
|
|
ThreadUnlock();
|
|
}
|
|
#endif
|
|
|
|
// Vismatrix public
|
|
#ifdef HLRAD_TRANSPARENCY_CPP
|
|
static bool CheckVisBitSparse(unsigned x, unsigned y
|
|
#ifdef HLRAD_HULLU
|
|
, vec3_t &transparency_out
|
|
, unsigned int &next_index
|
|
#endif
|
|
)
|
|
{
|
|
#ifdef HLRAD_HULLU
|
|
int offset;
|
|
#else
|
|
unsigned offset;
|
|
#endif
|
|
|
|
#ifdef HLRAD_HULLU
|
|
VectorFill(transparency_out, 1.0);
|
|
#endif
|
|
|
|
if (x == y)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
#ifdef HLRAD_HULLU
|
|
const unsigned a = x;
|
|
const unsigned b = y;
|
|
#endif
|
|
|
|
if (x > y)
|
|
{
|
|
#ifndef HLRAD_HULLU
|
|
const unsigned a = x;
|
|
const unsigned b = y;
|
|
#endif
|
|
x = b;
|
|
y = a;
|
|
}
|
|
|
|
if (x > g_num_patches)
|
|
{
|
|
Warning("in CheckVisBit(), x > num_patches");
|
|
}
|
|
if (y > g_num_patches)
|
|
{
|
|
Warning("in CheckVisBit(), y > num_patches");
|
|
}
|
|
|
|
if ((offset = IsVisbitInArray(x, y)) != -1)
|
|
{
|
|
#ifdef HLRAD_HULLU
|
|
if(g_customshadow_with_bouncelight)
|
|
{
|
|
GetTransparency(a, b, transparency_out, next_index);
|
|
}
|
|
#endif
|
|
return s_vismatrix[x].row[offset].values & (1 << (y & 7));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#else /*HLRAD_TRANSPARENCY_CPP*/
|
|
static bool CheckVisBitSparse(unsigned x, unsigned y
|
|
#ifdef HLRAD_HULLU
|
|
, vec3_t &transparency_out
|
|
#endif
|
|
)
|
|
{
|
|
unsigned offset;
|
|
|
|
if (x == y)
|
|
{
|
|
#ifdef HLRAD_HULLU
|
|
VectorFill(transparency_out, 1.0);
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
if (x > y)
|
|
{
|
|
const unsigned a = x;
|
|
const unsigned b = y;
|
|
x = b;
|
|
y = a;
|
|
}
|
|
|
|
if (x > g_num_patches)
|
|
{
|
|
Warning("in CheckVisBit(), x > num_patches");
|
|
}
|
|
if (y > g_num_patches)
|
|
{
|
|
Warning("in CheckVisBit(), y > num_patches");
|
|
}
|
|
|
|
if ((offset = IsVisbitInArray(x, y)) != -1)
|
|
{
|
|
#ifdef HLRAD_HULLU
|
|
if(g_customshadow_with_bouncelight)
|
|
{
|
|
vec3_t tmp = {1.0, 1.0, 1.0};
|
|
FindOpacity(x, y, tmp);
|
|
VectorCopy(tmp, transparency_out);
|
|
}
|
|
else
|
|
{
|
|
VectorFill(transparency_out, 1.0);
|
|
}
|
|
#endif
|
|
return s_vismatrix[x].row[offset].values & (1 << (y & 7));
|
|
}
|
|
#ifdef HLRAD_HULLU
|
|
VectorFill(transparency_out, 1.0);
|
|
#endif
|
|
return 0;
|
|
}
|
|
#endif /*HLRAD_TRANSPARENCY_CPP*/
|
|
|
|
/*
|
|
* ==============
|
|
* TestPatchToFace
|
|
*
|
|
* Sets vis bits for all patches in the face
|
|
* ==============
|
|
*/
|
|
static void TestPatchToFace(const unsigned patchnum, const int facenum, const int head
|
|
#ifdef HLRAD_ENTITYBOUNCE_FIX
|
|
, byte *pvs
|
|
#endif
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
, bool uncompressedcolumn[MAX_SPARSE_VISMATRIX_PATCHES]
|
|
#endif
|
|
)
|
|
{
|
|
patch_t* patch = &g_patches[patchnum];
|
|
patch_t* patch2 = g_face_patches[facenum];
|
|
|
|
// if emitter is behind that face plane, skip all patches
|
|
|
|
if (patch2)
|
|
{
|
|
const dplane_t* plane2 = getPlaneFromFaceNumber(facenum);
|
|
|
|
#ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN
|
|
if (DotProduct (patch->origin, plane2->normal) > PatchPlaneDist (patch2) + ON_EPSILON - patch->emitter_range)
|
|
#else
|
|
if (DotProduct(patch->origin, plane2->normal) > (PatchPlaneDist(patch2) + MINIMUM_PATCH_DISTANCE))
|
|
#endif
|
|
{
|
|
// we need to do a real test
|
|
const dplane_t* plane = getPlaneFromFaceNumber(patch->faceNumber);
|
|
|
|
for (; patch2; patch2 = patch2->next)
|
|
{
|
|
unsigned m = patch2 - g_patches;
|
|
|
|
#ifdef HLRAD_HULLU
|
|
vec3_t transparency = {1.0,1.0,1.0};
|
|
#endif
|
|
#ifdef HLRAD_OPAQUE_STYLE
|
|
int opaquestyle = -1;
|
|
#endif
|
|
|
|
// check vis between patch and patch2
|
|
// if bit has not already been set
|
|
// && v2 is not behind light plane
|
|
// && v2 is visible from v1
|
|
if (m > patchnum)
|
|
{
|
|
#ifdef HLRAD_ENTITYBOUNCE_FIX
|
|
if (patch2->leafnum == 0 || !(pvs[(patch2->leafnum - 1) >> 3] & (1 << ((patch2->leafnum - 1) & 7))))
|
|
{
|
|
continue;
|
|
}
|
|
#endif
|
|
#ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN
|
|
vec3_t origin1, origin2;
|
|
vec3_t delta;
|
|
vec_t dist;
|
|
VectorSubtract (patch->origin, patch2->origin, delta);
|
|
dist = VectorLength (delta);
|
|
if (dist < patch2->emitter_range - ON_EPSILON)
|
|
{
|
|
GetAlternateOrigin (patch->origin, plane->normal, patch2, origin2);
|
|
}
|
|
else
|
|
{
|
|
VectorCopy (patch2->origin, origin2);
|
|
}
|
|
if (DotProduct (origin2, plane->normal) <= PatchPlaneDist (patch) + MINIMUM_PATCH_DISTANCE)
|
|
{
|
|
continue;
|
|
}
|
|
if (dist < patch->emitter_range - ON_EPSILON)
|
|
{
|
|
GetAlternateOrigin (patch2->origin, plane2->normal, patch, origin1);
|
|
}
|
|
else
|
|
{
|
|
VectorCopy (patch->origin, origin1);
|
|
}
|
|
if (DotProduct (origin1, plane2->normal) <= PatchPlaneDist (patch2) + MINIMUM_PATCH_DISTANCE)
|
|
{
|
|
continue;
|
|
}
|
|
#else
|
|
if (DotProduct(patch2->origin, plane->normal) <= (PatchPlaneDist(patch) + MINIMUM_PATCH_DISTANCE))
|
|
{
|
|
continue;
|
|
}
|
|
#endif
|
|
#ifdef HLRAD_WATERBLOCKLIGHT
|
|
if (TestLine(
|
|
#ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN
|
|
origin1, origin2
|
|
#else
|
|
patch->origin, patch2->origin
|
|
#endif
|
|
) != CONTENTS_EMPTY)
|
|
#else
|
|
if (TestLine_r(head,
|
|
#ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN
|
|
origin1, origin2
|
|
#else
|
|
patch->origin, patch2->origin
|
|
#endif
|
|
) != CONTENTS_EMPTY)
|
|
#endif
|
|
{
|
|
continue;
|
|
}
|
|
if (TestSegmentAgainstOpaqueList(
|
|
#ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN
|
|
origin1, origin2
|
|
#else
|
|
patch->origin, patch2->origin
|
|
#endif
|
|
#ifdef HLRAD_HULLU
|
|
, transparency
|
|
#endif
|
|
#ifdef HLRAD_OPAQUE_STYLE
|
|
, opaquestyle
|
|
#endif
|
|
))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
#ifdef HLRAD_OPAQUE_STYLE_BOUNCE
|
|
if (opaquestyle != -1)
|
|
{
|
|
AddStyleToStyleArray (m, patchnum, opaquestyle);
|
|
AddStyleToStyleArray (patchnum, m, opaquestyle);
|
|
}
|
|
#endif
|
|
|
|
#ifdef HLRAD_HULLU
|
|
#ifdef HLRAD_TRANSPARENCY_CPP
|
|
if(g_customshadow_with_bouncelight && !VectorCompare(transparency, vec3_one) )
|
|
{
|
|
AddTransparencyToRawArray(patchnum, m, transparency);
|
|
}
|
|
#else
|
|
// transparency face fix table
|
|
if(g_customshadow_with_bouncelight && fabs(VectorAvg(transparency) - 1.0) < 0.001)
|
|
{
|
|
while(s_transparency_count>=s_max_transparency_count)
|
|
{
|
|
//new size
|
|
unsigned long oldsize = s_max_transparency_count;
|
|
s_max_transparency_count += 128;
|
|
|
|
//realloc
|
|
s_transparency_list = (transparency_t*)realloc(s_transparency_list, s_max_transparency_count * sizeof(transparency_t));
|
|
|
|
// clean new memory
|
|
memset(&s_transparency_list[oldsize], 0, sizeof(transparency_t) * 128);
|
|
}
|
|
|
|
//add to array
|
|
VectorCopy(transparency, s_transparency_list[s_transparency_count].transparency);
|
|
s_transparency_list[s_transparency_count].y = m;
|
|
s_transparency_list[s_transparency_count].x = patchnum;
|
|
|
|
s_transparency_count++;
|
|
}
|
|
#endif
|
|
#endif /*HLRAD_HULLU*/
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
uncompressedcolumn[m] = true;
|
|
#else
|
|
SetVisBit(m, patchnum);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef HLRAD_VISMATRIX_NOMARKSURFACES
|
|
/*
|
|
* ==============
|
|
* BuildVisRow
|
|
*
|
|
* Calc vis bits from a single patch
|
|
* ==============
|
|
*/
|
|
static void BuildVisRow(const int patchnum, byte* pvs, const int head)
|
|
{
|
|
int j, k, l;
|
|
byte face_tested[MAX_MAP_FACES];
|
|
dleaf_t* leaf;
|
|
|
|
memset(face_tested, 0, g_numfaces);
|
|
|
|
// leaf 0 is the solid leaf (skipped)
|
|
#ifdef HLRAD_VIS_FIX
|
|
for (j = 1, leaf = g_dleafs + 1; j < 1 + g_dmodels[0].visleafs; j++, leaf++)
|
|
#else
|
|
for (j = 1, leaf = g_dleafs + 1; j < g_numleafs; j++, leaf++)
|
|
#endif
|
|
{
|
|
if (!(pvs[(j - 1) >> 3] & (1 << ((j - 1) & 7))))
|
|
{
|
|
continue; // not in pvs
|
|
}
|
|
for (k = 0; k < leaf->nummarksurfaces; k++)
|
|
{
|
|
l = g_dmarksurfaces[leaf->firstmarksurface + k];
|
|
|
|
// faces can be marksurfed by multiple leaves, but
|
|
// don't bother testing again
|
|
if (face_tested[l])
|
|
continue;
|
|
face_tested[l] = 1;
|
|
|
|
TestPatchToFace(patchnum, l, head
|
|
#ifdef HLRAD_ENTITYBOUNCE_FIX
|
|
, pvs
|
|
#endif
|
|
);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* ===========
|
|
* BuildVisLeafs
|
|
*
|
|
* This is run by multiple threads
|
|
* ===========
|
|
*/
|
|
#ifdef SYSTEM_WIN32
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 4100) // unreferenced formal parameter
|
|
#endif
|
|
static void BuildVisLeafs(int threadnum)
|
|
{
|
|
int i;
|
|
int lface, facenum, facenum2;
|
|
byte pvs[(MAX_MAP_LEAFS + 7) / 8];
|
|
dleaf_t* srcleaf;
|
|
dleaf_t* leaf;
|
|
patch_t* patch;
|
|
int head;
|
|
unsigned patchnum;
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
bool *uncompressedcolumn = (bool *)malloc (MAX_SPARSE_VISMATRIX_PATCHES * sizeof (bool));
|
|
hlassume (uncompressedcolumn != NULL, assume_NoMemory);
|
|
#endif
|
|
|
|
while (1)
|
|
{
|
|
//
|
|
// build a minimal BSP tree that only
|
|
// covers areas relevent to the PVS
|
|
//
|
|
i = GetThreadWork();
|
|
if (i == -1)
|
|
{
|
|
break;
|
|
}
|
|
i++; // skip leaf 0
|
|
srcleaf = &g_dleafs[i];
|
|
#ifdef HLRAD_WITHOUTVIS
|
|
if (!g_visdatasize)
|
|
{
|
|
#ifdef ZHLT_DecompressVis_FIX
|
|
memset (pvs, 255, (g_dmodels[0].visleafs + 7) / 8);
|
|
#else
|
|
memset(pvs, 255, (g_numleafs + 7) / 8);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
#ifdef HLRAD_VIS_FIX
|
|
if (srcleaf->visofs == -1)
|
|
{
|
|
Developer (DEVELOPER_LEVEL_ERROR, "Error: No visdata for leaf %d\n", i);
|
|
continue;
|
|
}
|
|
#endif
|
|
DecompressVis(&g_dvisdata[srcleaf->visofs], pvs, sizeof(pvs));
|
|
#ifdef HLRAD_WITHOUTVIS
|
|
}
|
|
#endif
|
|
head = 0;
|
|
|
|
//
|
|
// go through all the faces inside the
|
|
// leaf, and process the patches that
|
|
// actually have origins inside
|
|
//
|
|
#ifdef HLRAD_VISMATRIX_NOMARKSURFACES
|
|
for (facenum = 0; facenum < g_numfaces; facenum++)
|
|
{
|
|
for (patch = g_face_patches[facenum]; patch; patch = patch->next)
|
|
{
|
|
if (patch->leafnum != i)
|
|
continue;
|
|
patchnum = patch - g_patches;
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
for (int m = 0; m < g_num_patches; m++)
|
|
{
|
|
uncompressedcolumn[m] = false;
|
|
}
|
|
#endif
|
|
for (facenum2 = facenum + 1; facenum2 < g_numfaces; facenum2++)
|
|
TestPatchToFace (patchnum, facenum2, head, pvs
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
, uncompressedcolumn
|
|
#endif
|
|
);
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
SetVisColumn (patchnum, uncompressedcolumn);
|
|
#endif
|
|
}
|
|
}
|
|
#else
|
|
for (lface = 0; lface < srcleaf->nummarksurfaces; lface++)
|
|
{
|
|
facenum = g_dmarksurfaces[srcleaf->firstmarksurface + lface];
|
|
for (patch = g_face_patches[facenum]; patch; patch = patch->next)
|
|
{
|
|
#ifdef HLRAD_ENTITYBOUNCE_FIX
|
|
if (patch->leafnum != i)
|
|
{
|
|
continue;
|
|
}
|
|
#else
|
|
leaf = PointInLeaf(patch->origin);
|
|
if (leaf != srcleaf)
|
|
{
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
patchnum = patch - g_patches;
|
|
// build to all other world leafs
|
|
BuildVisRow(patchnum, pvs, head);
|
|
|
|
// build to bmodel faces
|
|
if (g_nummodels < 2)
|
|
{
|
|
continue;
|
|
}
|
|
for (facenum2 = g_dmodels[1].firstface; facenum2 < g_numfaces; facenum2++)
|
|
{
|
|
TestPatchToFace(patchnum, facenum2, head
|
|
#ifdef HLRAD_ENTITYBOUNCE_FIX
|
|
, pvs
|
|
#endif
|
|
);
|
|
}
|
|
}
|
|
}
|
|
#ifdef HLRAD_ENTITYBOUNCE_FIX
|
|
if (g_nummodels >= 2)
|
|
{
|
|
for (facenum = g_dmodels[1].firstface; facenum < g_numfaces; facenum++)
|
|
{
|
|
for (patch = g_face_patches[facenum]; patch; patch = patch->next)
|
|
{
|
|
if (patch->leafnum != i)
|
|
continue;
|
|
patchnum = patch - g_patches;
|
|
// skip BuildVisRow here because entity patchnums are always bigger than world patchnums.
|
|
for (facenum2 = g_dmodels[1].firstface; facenum2 < g_numfaces; facenum2++)
|
|
TestPatchToFace(patchnum, facenum2, head, pvs);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
#ifdef HLRAD_SPARSEVISMATRIX_FAST
|
|
free (uncompressedcolumn);
|
|
#endif
|
|
}
|
|
|
|
#ifdef SYSTEM_WIN32
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
/*
|
|
* ==============
|
|
* BuildVisMatrix
|
|
* ==============
|
|
*/
|
|
static void BuildVisMatrix()
|
|
{
|
|
s_vismatrix = (sparse_column_t*)AllocBlock(g_num_patches * sizeof(sparse_column_t));
|
|
|
|
if (!s_vismatrix)
|
|
{
|
|
Log("Failed to allocate vismatrix");
|
|
hlassume(s_vismatrix != NULL, assume_NoMemory);
|
|
}
|
|
|
|
#ifdef HLRAD_VIS_FIX
|
|
NamedRunThreadsOn(g_dmodels[0].visleafs, g_estimate, BuildVisLeafs);
|
|
#else
|
|
NamedRunThreadsOn(g_numleafs - 1, g_estimate, BuildVisLeafs);
|
|
#endif
|
|
}
|
|
|
|
static void FreeVisMatrix()
|
|
{
|
|
if (s_vismatrix)
|
|
{
|
|
unsigned x;
|
|
sparse_column_t* item;
|
|
|
|
for (x = 0, item = s_vismatrix; x < g_num_patches; x++, item++)
|
|
{
|
|
if (item->row)
|
|
{
|
|
free(item->row);
|
|
}
|
|
}
|
|
if (FreeBlock(s_vismatrix))
|
|
{
|
|
s_vismatrix = NULL;
|
|
}
|
|
else
|
|
{
|
|
Warning("Unable to free vismatrix");
|
|
}
|
|
}
|
|
|
|
#ifndef HLRAD_TRANSPARENCY_CPP
|
|
#ifdef HLRAD_HULLU
|
|
if(s_transparency_list)
|
|
{
|
|
free(s_transparency_list);
|
|
s_transparency_list = NULL;
|
|
}
|
|
s_transparency_count = s_max_transparency_count = 0;
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
|
|
static void DumpVismatrixInfo()
|
|
{
|
|
unsigned totals[8];
|
|
#ifdef ZHLT_64BIT_FIX
|
|
size_t total_vismatrix_memory;
|
|
#else
|
|
unsigned total_vismatrix_memory;
|
|
#endif
|
|
total_vismatrix_memory = sizeof(sparse_column_t) * g_num_patches;
|
|
|
|
sparse_column_t* column_end = s_vismatrix + g_num_patches;
|
|
sparse_column_t* column = s_vismatrix;
|
|
|
|
memset(totals, 0, sizeof(totals));
|
|
|
|
while (column < column_end)
|
|
{
|
|
total_vismatrix_memory += column->count * sizeof(sparse_row_t);
|
|
column++;
|
|
}
|
|
|
|
Log("%-20s: %5.1f megs\n", "visibility matrix", total_vismatrix_memory / (1024 * 1024.0));
|
|
}
|
|
|
|
//
|
|
// end old vismat.c
|
|
////////////////////////////
|
|
|
|
void MakeScalesSparseVismatrix()
|
|
{
|
|
char transferfile[_MAX_PATH];
|
|
|
|
hlassume(g_num_patches < MAX_SPARSE_VISMATRIX_PATCHES, assume_MAX_PATCHES);
|
|
|
|
#ifdef ZHLT_DEFAULTEXTENSION_FIX
|
|
safe_snprintf(transferfile, _MAX_PATH, "%s.inc", g_Mapname);
|
|
#else
|
|
safe_strncpy(transferfile, g_source, _MAX_PATH);
|
|
StripExtension(transferfile);
|
|
DefaultExtension(transferfile, ".inc");
|
|
#endif
|
|
|
|
if (!g_incremental || !readtransfers(transferfile, g_num_patches))
|
|
{
|
|
// determine visibility between g_patches
|
|
BuildVisMatrix();
|
|
DumpVismatrixInfo();
|
|
g_CheckVisBit = CheckVisBitSparse;
|
|
|
|
#ifdef HLRAD_HULLU
|
|
#ifdef HLRAD_TRANSPARENCY_CPP
|
|
CreateFinalTransparencyArrays("custom shadow array");
|
|
#else
|
|
if((s_max_transparency_count*sizeof(transparency_t))>=(1024 * 1024))
|
|
Log("%-20s: %5.1f megs\n", "custom shadow array", (s_max_transparency_count*sizeof(transparency_t)) / (1024 * 1024.0));
|
|
else if(s_transparency_count)
|
|
Log("%-20s: %5.1f kilos\n", "custom shadow array", (s_max_transparency_count*sizeof(transparency_t)) / 1024.0);
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef HLRAD_HULLU
|
|
NamedRunThreadsOn(g_num_patches, g_estimate, MakeScales);
|
|
#else
|
|
if(g_rgb_transfers)
|
|
{NamedRunThreadsOn(g_num_patches, g_estimate, MakeRGBScales);}
|
|
else
|
|
{NamedRunThreadsOn(g_num_patches, g_estimate, MakeScales);}
|
|
#endif
|
|
FreeVisMatrix();
|
|
#ifdef HLRAD_HULLU
|
|
#ifdef HLRAD_TRANSPARENCY_CPP
|
|
FreeTransparencyArrays();
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef HLRAD_NOSWAP
|
|
// invert the transfers for gather vs scatter
|
|
#ifndef HLRAD_HULLU
|
|
NamedRunThreadsOnIndividual(g_num_patches, g_estimate, SwapTransfers);
|
|
#else
|
|
if(g_rgb_transfers)
|
|
{NamedRunThreadsOnIndividual(g_num_patches, g_estimate, SwapRGBTransfers);}
|
|
else
|
|
{NamedRunThreadsOnIndividual(g_num_patches, g_estimate, SwapTransfers);}
|
|
#endif
|
|
#endif /*HLRAD_NOSWAP*/
|
|
if (g_incremental)
|
|
{
|
|
writetransfers(transferfile, g_num_patches);
|
|
}
|
|
else
|
|
{
|
|
_unlink(transferfile);
|
|
}
|
|
// release visibility matrix
|
|
DumpTransfersMemoryUsage();
|
|
#ifdef HLRAD_OPAQUE_STYLE_BOUNCE
|
|
CreateFinalStyleArrays ("dynamic shadow array");
|
|
#endif
|
|
}
|
|
}
|