void compress_compatability_test () { unsigned char *v = (unsigned char *)malloc (16u); memset (v, 0, 16u); if (sizeof(char) !=1 || sizeof(unsigned int) != 4 || sizeof(float) != 4) fail (); *(float *)(v+1) = 0.123f; if (*(unsigned int *)v != 4226247936u || *(unsigned int *)(v+1) != 1039918957u) fail (); *(float *)(v+1) = -58; if (*(unsigned int *)v != 1744830464u || *(unsigned int *)(v+1) != 3261595648u) fail (); float f[5] = {0.123f, 1.f, 0.f, 0.123f, 0.f}; memset (v, ~0, 16u); vector_compress (VECTOR24, v, &f[0], &f[1], &f[2]); float_compress (FLOAT16, v+6, &f[3]); float_compress (FLOAT16, v+4, &f[4]); if (((unsigned int *)v)[0] != 4286318595u || ((unsigned int *)v)[1] != 3753771008u) fail (); float_decompress (FLOAT16, v+6, &f[3]); float_decompress (FLOAT16, v+4, &f[4]); vector_decompress (VECTOR24, v, &f[0], &f[1], &f[2]); float ans[5] = {0.109375f,1.015625f,0.015625f,0.123001f,0.000000f}; int i; for (i=0; i<5; ++i) if (f[i]-ans[i] > 0.00001f || f[i]-ans[i] < -0.00001f) fail (); free (v); }
void MakeScales(const int threadnum) { int i; unsigned j; vec3_t delta; vec_t dist; int count; float trans; patch_t* patch; patch_t* patch2; vec3_t origin; vec_t area; const vec_t* normal1; const vec_t* normal2; #ifdef HLRAD_HULLU #ifdef HLRAD_TRANSPARENCY_CPP unsigned int fastfind_index = 0; #endif #endif vec_t total; #ifdef HLRAD_TRANSFERDATA_COMPRESS transfer_raw_index_t* tIndex; float* tData; transfer_raw_index_t* tIndex_All = (transfer_raw_index_t*)AllocBlock(sizeof(transfer_index_t) * MAX_PATCHES); float* tData_All = (float*)AllocBlock(sizeof(float) * MAX_PATCHES); #else transfer_raw_index_t* tIndex; transfer_data_t* tData; transfer_raw_index_t* tIndex_All = (transfer_raw_index_t*)AllocBlock(sizeof(transfer_index_t) * MAX_PATCHES); transfer_data_t* tData_All = (transfer_data_t*)AllocBlock(sizeof(transfer_data_t) * MAX_PATCHES); #endif count = 0; while (1) { i = GetThreadWork(); if (i == -1) break; patch = g_patches + i; patch->iIndex = 0; patch->iData = 0; #ifndef HLRAD_TRANSNONORMALIZE total = 0.0; #endif tIndex = tIndex_All; tData = tData_All; VectorCopy(patch->origin, origin); normal1 = getPlaneFromFaceNumber(patch->faceNumber)->normal; area = patch->area; #ifdef HLRAD_TRANSLUCENT vec3_t backorigin; vec3_t backnormal; if (patch->translucent_b) { VectorMA (patch->origin, -(g_translucentdepth + 2*PATCH_HUNT_OFFSET), normal1, backorigin); VectorSubtract (vec3_origin, normal1, backnormal); } #endif #ifdef HLRAD_DIVERSE_LIGHTING bool lighting_diversify; vec_t lighting_power; vec_t lighting_scale; int miptex = g_texinfo[g_dfaces[patch->faceNumber].texinfo].miptex; lighting_power = g_lightingconeinfo[miptex][0]; lighting_scale = g_lightingconeinfo[miptex][1]; lighting_diversify = (lighting_power != 1.0 || lighting_scale != 1.0); #endif // find out which patch2's will collect light // from patch // HLRAD_NOSWAP: patch collect light from patch2 for (j = 0, patch2 = g_patches; j < g_num_patches; j++, patch2++) { vec_t dot1; vec_t dot2; #ifdef HLRAD_HULLU vec3_t transparency = {1.0,1.0,1.0}; #endif #ifdef HLRAD_TRANSLUCENT bool useback; useback = false; #endif if (!g_CheckVisBit(i, j #ifdef HLRAD_HULLU , transparency #ifdef HLRAD_TRANSPARENCY_CPP , fastfind_index #endif #endif ) || (i == j)) { #ifdef HLRAD_TRANSLUCENT if (patch->translucent_b) { if ((i == j) || !CheckVisBitBackwards(i, j, backorigin, backnormal #ifdef HLRAD_HULLU , transparency #endif )) { continue; } useback = true; } else { continue; } #else continue; #endif } normal2 = getPlaneFromFaceNumber(patch2->faceNumber)->normal; // calculate transferemnce VectorSubtract(patch2->origin, origin, delta); #ifdef HLRAD_TRANSLUCENT if (useback) { VectorSubtract (patch2->origin, backorigin, delta); } #endif #ifdef HLRAD_ACCURATEBOUNCE // move emitter back to its plane VectorMA (delta, -PATCH_HUNT_OFFSET, normal2, delta); #endif dist = VectorNormalize(delta); dot1 = DotProduct(delta, normal1); #ifdef HLRAD_TRANSLUCENT if (useback) { dot1 = DotProduct (delta, backnormal); } #endif dot2 = -DotProduct(delta, normal2); #ifdef HLRAD_ACCURATEBOUNCE #ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN bool light_behind_surface = false; if (dot1 <= NORMAL_EPSILON) { light_behind_surface = true; } #else if (dot1 <= NORMAL_EPSILON) { continue; } #endif if (dot2 * dist <= MINIMUM_PATCH_DISTANCE) { continue; } #endif #ifdef HLRAD_DIVERSE_LIGHTING if (lighting_diversify #ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN && !light_behind_surface #endif ) { dot1 = lighting_scale * pow (dot1, lighting_power); } #endif trans = (dot1 * dot2) / (dist * dist); // Inverse square falloff factoring angle between patch normals #ifdef HLRAD_TRANSWEIRDFIX #ifdef HLRAD_NOSWAP if (trans * patch2->area > 0.8f) trans = 0.8f / patch2->area; #else // HLRAD_TRANSWEIRDFIX: // we should limit "trans(patch2receive) * patch1area" // instead of "trans(patch2receive) * patch2area". // also raise "0.4f" to "0.8f" ( 0.8/Q_PI = 1/4). if (trans * area > 0.8f) trans = 0.8f / area; #endif #endif #ifdef HLRAD_ACCURATEBOUNCE if (dist < patch2->emitter_range - ON_EPSILON) { #ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN if (light_behind_surface) { trans = 0.0; } #endif vec_t sightarea; const vec_t *receiver_origin; const vec_t *receiver_normal; const Winding *emitter_winding; receiver_origin = origin; receiver_normal = normal1; #ifdef HLRAD_TRANSLUCENT if (useback) { receiver_origin = backorigin; receiver_normal = backnormal; } #endif emitter_winding = patch2->winding; sightarea = CalcSightArea (receiver_origin, receiver_normal, emitter_winding, patch2->emitter_skylevel #ifdef HLRAD_DIVERSE_LIGHTING , lighting_power, lighting_scale #endif ); vec_t frac; frac = dist / patch2->emitter_range; frac = (frac - 0.5f) * 2.0f; // make a smooth transition between the two methods frac = max (0, min (frac, 1)); trans = frac * trans + (1 - frac) * (sightarea / patch2->area); // because later we will multiply this back } #ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN else { if (light_behind_surface) { continue; } } #endif #endif #ifdef HLRAD_ACCURATEBOUNCE_REDUCEAREA trans *= patch2->exposure; #endif #ifdef HLRAD_HULLU trans = trans * VectorAvg(transparency); //hullu: add transparency effect #endif #ifdef HLRAD_TRANSLUCENT if (patch->translucent_b) { if (useback) { trans *= VectorAvg (patch->translucent_v); } else { trans *= 1 - VectorAvg (patch->translucent_v); } } #endif #ifndef HLRAD_ACCURATEBOUNCE if (trans >= 0) #endif { #ifndef HLRAD_TRANSWEIRDFIX #ifdef HLRAD_NOSWAP send = trans * area; #else send = trans * patch2->area; #endif // Caps light from getting weird if (send > 0.4f) { #ifdef HLRAD_NOSWAP trans = 0.4f / area; #else trans = 0.4f / patch2->area; #endif send = 0.4f; } #endif /*HLRAD_TRANSWEIRDFIX*/ #ifndef HLRAD_TRANSNONORMALIZE total += send; #endif #ifdef HLRAD_TRANSFERDATA_COMPRESS trans = trans * patch2->area; #else // scale to 16 bit (black magic) // BUG: (in MakeRGBScales) convert to integer will lose data. --vluzacn #ifdef HLRAD_NOSWAP trans = trans * patch2->area * INVERSE_TRANSFER_SCALE; #else trans = trans * area * INVERSE_TRANSFER_SCALE; #endif /*HLRAD_NOSWAP*/ if (trans >= TRANSFER_SCALE_MAX) { trans = TRANSFER_SCALE_MAX; } #endif } #ifndef HLRAD_ACCURATEBOUNCE else { #if 0 Warning("transfer < 0 (%f): dist=(%f)\n" " dot1=(%f) patch@(%4.3f %4.3f %4.3f) normal(%4.3f %4.3f %4.3f)\n" " dot2=(%f) patch@(%4.3f %4.3f %4.3f) normal(%4.3f %4.3f %4.3f)\n", trans, dist, dot1, patch->origin[0], patch->origin[1], patch->origin[2], patch->normal[0], patch->normal[1], patch->normal[2], dot2, patch2->origin[0], patch2->origin[1], patch2->origin[2], patch2->normal[0], patch2->normal[1], patch2->normal[2]); #endif trans = 0.0; } #endif #ifdef HLRAD_ACCURATEBOUNCE if (trans <= 0.0) { continue; } #endif *tData = trans; *tIndex = j; tData++; tIndex++; patch->iData++; count++; } // copy the transfers out if (patch->iData) { #ifdef HLRAD_TRANSFERDATA_COMPRESS unsigned data_size = patch->iData * float_size[g_transfer_compress_type] + unused_size; #else unsigned data_size = patch->iData * sizeof(transfer_data_t); #endif patch->tData = (transfer_data_t*)AllocBlock(data_size); patch->tIndex = CompressTransferIndicies(tIndex_All, patch->iData, &patch->iIndex); hlassume(patch->tData != NULL, assume_NoMemory); hlassume(patch->tIndex != NULL, assume_NoMemory); ThreadLock(); g_transfer_data_bytes += data_size; ThreadUnlock(); #ifdef HLRAD_REFLECTIVITY total = 1 / Q_PI; #else #ifdef HLRAD_TRANSNONORMALIZE #ifdef HLRAD_TRANSTOTAL_HACK total = g_transtotal_hack / Q_PI; #else total = 0.5 / Q_PI; #endif #else // BAD assumption when there is SKY. // // normalize all transfers so exactly 50% of the light // is transfered to the surroundings // total = 0.5 / total; #endif #endif { #ifdef HLRAD_TRANSFERDATA_COMPRESS unsigned x; transfer_data_t* t1 = patch->tData; float* t2 = tData_All; float f; for (x = 0; x < patch->iData; x++, t1+=float_size[g_transfer_compress_type], t2++) { f = (*t2) * total; float_compress (g_transfer_compress_type, t1, &f); } #else unsigned x; transfer_data_t* t1 = patch->tData; transfer_data_t* t2 = tData_All; for (x = 0; x < patch->iData; x++, t1++, t2++) { (*t1) = (*t2) * total; } #endif } } } FreeBlock(tIndex_All); FreeBlock(tData_All); ThreadLock(); g_total_transfer += count; ThreadUnlock(); }