vhlt/hlrad/transparency.cpp
2016-09-21 00:07:53 +03:00

452 lines
12 KiB
C++

#pragma warning(disable: 4018) //amckern - 64bit - '<' Singed/Unsigned Mismatch
//
// Transparency Arrays for sparse and vismatrix methods
//
#include "qrad.h"
#ifdef HLRAD_HULLU
#ifndef HLRAD_TRANSPARENCY_FAST
#define TRANS_LIST_GROWTH 64
#define RAW_LIST_GROWTH 2048
#endif
typedef struct {
unsigned p1;
unsigned p2;
unsigned data_index;
} transList_t;
static vec3_t * s_trans_list = NULL;
static unsigned int s_trans_count = 0;
static unsigned int s_max_trans_count = 0;
static transList_t* s_raw_list = NULL;
static unsigned int s_raw_count = 0;
static unsigned int s_max_raw_count = 0; // Current array maximum (used for reallocs)
static transList_t* s_sorted_list = NULL; // Sorted first by p1 then p2
static unsigned int s_sorted_count = 0;
const vec3_t vec3_one = {1.0,1.0,1.0};
//===============================================
// AddTransparencyToRawArray
//===============================================
static unsigned AddTransparencyToDataList(const vec3_t trans)
{
//Check if this value is in list already
#ifdef ZHLT_64BIT_FIX
for(unsigned int i = 0; i < s_trans_count; i++)
#else
for(int i = 0; i < s_trans_count; i++)
#endif
{
if( VectorCompare( trans, s_trans_list[i] ) )
{
return i;
}
}
//realloc if needed
while( s_trans_count >= s_max_trans_count )
{
unsigned int old_max_count = s_max_trans_count;
#ifdef HLRAD_TRANSPARENCY_FAST
s_max_trans_count = qmax (64u, (unsigned int)((double)s_max_trans_count * 1.41));
#else
s_max_trans_count += TRANS_LIST_GROWTH;
#endif
#ifdef ZHLT_64BIT_FIX
if (s_max_trans_count >= (unsigned int)INT_MAX)
{
Error ("AddTransparencyToDataList: array size exceeded INT_MAX");
}
#endif
s_trans_list = (vec3_t *)realloc( s_trans_list, sizeof(vec3_t) * s_max_trans_count );
#ifdef HLRAD_HLASSUMENOMEMORY
hlassume (s_trans_list != NULL, assume_NoMemory);
#endif
#ifdef HLRAD_TRANSPARENCY_FAST
memset( &s_trans_list[old_max_count], 0, sizeof(vec3_t) * (s_max_trans_count - old_max_count) );
#else
memset( &s_trans_list[old_max_count], 0, sizeof(vec3_t) * TRANS_LIST_GROWTH );
#endif
if( old_max_count == 0 )
{
VectorFill(s_trans_list[0], 1.0);
s_trans_count++;
}
}
VectorCopy(trans, s_trans_list[s_trans_count]);
return ( s_trans_count++ );
}
//===============================================
// AddTransparencyToRawArray
//===============================================
void AddTransparencyToRawArray(const unsigned p1, const unsigned p2, const vec3_t trans)
{
//make thread safe
ThreadLock();
unsigned data_index = AddTransparencyToDataList(trans);
//realloc if needed
while( s_raw_count >= s_max_raw_count )
{
unsigned int old_max_count = s_max_raw_count;
#ifdef HLRAD_TRANSPARENCY_FAST
s_max_raw_count = qmax (64u, (unsigned int)((double)s_max_raw_count * 1.41));
#else
s_max_raw_count += RAW_LIST_GROWTH;
#endif
#ifdef ZHLT_64BIT_FIX
if (s_max_raw_count >= (unsigned int)INT_MAX)
{
Error ("AddTransparencyToRawArray: array size exceeded INT_MAX");
}
#endif
s_raw_list = (transList_t *)realloc( s_raw_list, sizeof(transList_t) * s_max_raw_count );
#ifdef HLRAD_HLASSUMENOMEMORY
hlassume (s_raw_list != NULL, assume_NoMemory);
#endif
#ifdef HLRAD_TRANSPARENCY_FAST
memset( &s_raw_list[old_max_count], 0, sizeof(transList_t) * (s_max_raw_count - old_max_count) );
#else
memset( &s_raw_list[old_max_count], 0, sizeof(transList_t) * RAW_LIST_GROWTH );
#endif
}
s_raw_list[s_raw_count].p1 = p1;
s_raw_list[s_raw_count].p2 = p2;
s_raw_list[s_raw_count].data_index = data_index;
s_raw_count++;
//unlock list
ThreadUnlock();
}
//===============================================
// SortList
//===============================================
static int CDECL SortList(const void *a, const void *b)
{
const transList_t* item1 = (transList_t *)a;
const transList_t* item2 = (transList_t *)b;
if( item1->p1 == item2->p1 )
{
return item1->p2 - item2->p2;
}
else
{
return item1->p1 - item2->p1;
}
}
//===============================================
// CreateFinalTransparencyArrays
//===============================================
void CreateFinalTransparencyArrays(const char *print_name)
{
if( s_raw_count == 0 )
{
s_raw_list = NULL;
s_raw_count = s_max_raw_count = 0;
return;
}
//double sized (faster find function for sorted list)
s_sorted_count = s_raw_count * 2;
s_sorted_list = (transList_t *)malloc( sizeof(transList_t) * s_sorted_count );
#ifdef HLRAD_HLASSUMENOMEMORY
hlassume (s_sorted_list != NULL, assume_NoMemory);
#endif
//First half have p1>p2
for( unsigned int i = 0; i < s_raw_count; i++ )
{
s_sorted_list[i].p1 = s_raw_list[i].p2;
s_sorted_list[i].p2 = s_raw_list[i].p1;
s_sorted_list[i].data_index = s_raw_list[i].data_index;
}
//Second half have p1<p2
memcpy( &s_sorted_list[s_raw_count], s_raw_list, sizeof(transList_t) * s_raw_count );
//free old array
free( s_raw_list );
s_raw_list = NULL;
s_raw_count = s_max_raw_count = 0;
//need to sorted for fast search function
qsort( s_sorted_list, s_sorted_count, sizeof(transList_t), SortList );
#ifdef ZHLT_64BIT_FIX
size_t size = s_sorted_count * sizeof(transList_t) + s_max_trans_count * sizeof(vec3_t);
#else
unsigned size = s_sorted_count * sizeof(transList_t) + s_max_trans_count * sizeof(vec3_t);
#endif
if ( size > 1024 * 1024 )
Log("%-20s: %5.1f megs \n", print_name, (double)size / (1024.0 * 1024.0));
else if ( size > 1024 )
Log("%-20s: %5.1f kilos\n", print_name, (double)size / 1024.0);
else
Log("%-20s: %5.1f bytes\n", print_name, (double)size); //--vluzacn
Developer (DEVELOPER_LEVEL_MESSAGE, "\ts_trans_count=%d\ts_sorted_count=%d\n", s_trans_count, s_sorted_count); //--vluzacn
#if 0
int total_1 = 0;
for(int i = 0; i < s_sorted_count; i++)
{
Log("a: %7i b: %7i di: %10i r: %3.1f g: %3.1f b: %3.1f\n",
s_sorted_list[i].p1,
s_sorted_list[i].p2,
s_sorted_list[i].data_index,
s_trans_list[s_sorted_list[i].data_index][0],
s_trans_list[s_sorted_list[i].data_index][1],
s_trans_list[s_sorted_list[i].data_index][2]
);
total_1++;
}
vec3_t rgb;
int total_2 = 0;
for(unsigned int next_index = 0, a = 0; a < g_num_patches; a++)
{
for(unsigned int b = 0; b < g_num_patches; b++)
{
GetTransparency(a, b, rgb, next_index);
if(!VectorCompare(rgb,vec3_one))
{
Log("a: %7i b: %7i ni: %10i r: %3.1f g: %3.1f b: %3.1f\n",
a,
b,
next_index,
rgb[0],
rgb[1],
rgb[2]
);
total_2++;
}
}
}
Log("total1: %i\ntotal2: %i\n",total_1,total_2);
#endif
}
//===============================================
// FreeTransparencyArrays
//===============================================
void FreeTransparencyArrays( )
{
if (s_sorted_list) free(s_sorted_list);
if (s_trans_list) free(s_trans_list);
s_trans_list = NULL;
s_sorted_list = NULL;
s_max_trans_count = s_trans_count = s_sorted_count = 0;
}
//===============================================
// GetTransparency -- find transparency from list. remembers last location
//===============================================
void GetTransparency(const unsigned p1, const unsigned p2, vec3_t &trans, unsigned int &next_index)
{
VectorFill( trans, 1.0 );
for( unsigned i = next_index; i < s_sorted_count; i++ )
{
if ( s_sorted_list[i].p1 < p1 )
{
continue;
}
else if ( s_sorted_list[i].p1 == p1 )
{
if ( s_sorted_list[i].p2 < p2 )
{
continue;
}
else if ( s_sorted_list[i].p2 == p2 )
{
VectorCopy( s_trans_list[s_sorted_list[i].data_index], trans );
next_index = i + 1;
return;
}
else //if ( s_sorted_list[i].p2 > p2 )
{
next_index = i;
return;
}
}
else //if ( s_sorted_list[i].p1 > p1 )
{
next_index = i;
return;
}
}
next_index = s_sorted_count;
}
#endif /*HLRAD_HULLU*/
#ifdef HLRAD_OPAQUE_STYLE_BOUNCE
#ifndef HLRAD_TRANSPARENCY_FAST
#define STYLE_LIST_GROWTH 2048
#endif
typedef struct {
unsigned p1;
unsigned p2;
char style;
} styleList_t;
static styleList_t* s_style_list = NULL;
static unsigned int s_style_count = 0;
static unsigned int s_max_style_count = 0;
void AddStyleToStyleArray(const unsigned p1, const unsigned p2, const int style)
{
if (style == -1)
return;
//make thread safe
ThreadLock();
//realloc if needed
while( s_style_count >= s_max_style_count )
{
unsigned int old_max_count = s_max_style_count;
#ifdef HLRAD_TRANSPARENCY_FAST
s_max_style_count = qmax (64u, (unsigned int)((double)s_max_style_count * 1.41));
#else
s_max_style_count += STYLE_LIST_GROWTH;
#endif
#ifdef ZHLT_64BIT_FIX
if (s_max_style_count >= (unsigned int)INT_MAX)
{
Error ("AddStyleToStyleArray: array size exceeded INT_MAX");
}
#endif
s_style_list = (styleList_t *)realloc( s_style_list, sizeof(styleList_t) * s_max_style_count );
#ifdef HLRAD_HLASSUMENOMEMORY
hlassume (s_style_list != NULL, assume_NoMemory);
#endif
#ifdef HLRAD_TRANSPARENCY_FAST
memset( &s_style_list[old_max_count], 0, sizeof(styleList_t) * (s_max_style_count - old_max_count) );
#else
memset( &s_style_list[old_max_count], 0, sizeof(styleList_t) * STYLE_LIST_GROWTH );
#endif
}
s_style_list[s_style_count].p1 = p1;
s_style_list[s_style_count].p2 = p2;
s_style_list[s_style_count].style = (char)style;
s_style_count++;
//unlock list
ThreadUnlock();
}
static int CDECL SortStyleList(const void *a, const void *b)
{
const styleList_t* item1 = (styleList_t *)a;
const styleList_t* item2 = (styleList_t *)b;
if( item1->p1 == item2->p1 )
{
return item1->p2 - item2->p2;
}
else
{
return item1->p1 - item2->p1;
}
}
void CreateFinalStyleArrays(const char *print_name)
{
if( s_style_count == 0 )
{
return;
}
//need to sorted for fast search function
qsort( s_style_list, s_style_count, sizeof(styleList_t), SortStyleList );
#ifdef ZHLT_64BIT_FIX
size_t size = s_max_style_count * sizeof(styleList_t);
#else
unsigned size = s_max_style_count * sizeof(styleList_t);
#endif
if ( size > 1024 * 1024 )
Log("%-20s: %5.1f megs \n", print_name, (double)size / (1024.0 * 1024.0));
else if ( size > 1024 )
Log("%-20s: %5.1f kilos\n", print_name, (double)size / 1024.0);
else
Log("%-20s: %5.1f bytes\n", print_name, (double)size); //--vluzacn
}
void FreeStyleArrays( )
{
if (s_style_count) free(s_style_list);
s_style_list = NULL;
s_max_style_count = s_style_count = 0;
}
void GetStyle(const unsigned p1, const unsigned p2, int &style, unsigned int &next_index)
{
style = -1;
for( unsigned i = next_index; i < s_style_count; i++ )
{
if ( s_style_list[i].p1 < p1 )
{
continue;
}
else if ( s_style_list[i].p1 == p1 )
{
if ( s_style_list[i].p2 < p2 )
{
continue;
}
else if ( s_style_list[i].p2 == p2 )
{
style = (int)s_style_list[i].style;
next_index = i + 1;
return;
}
else //if ( s_style_list[i].p2 > p2 )
{
next_index = i;
return;
}
}
else //if ( s_style_list[i].p1 > p1 )
{
next_index = i;
return;
}
}
next_index = s_style_count;
}
#endif