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 MakeRGBScales(const int threadnum) { int i; unsigned j; vec3_t delta; vec_t dist; int count; float trans[3]; float trans_one; patch_t* patch; patch_t* patch2; vec3_t origin; vec_t area; const vec_t* normal1; const vec_t* normal2; #ifdef HLRAD_TRANSPARENCY_CPP unsigned int fastfind_index = 0; #endif vec_t total; #ifdef HLRAD_TRANSFERDATA_COMPRESS transfer_raw_index_t* tIndex; float* tRGBData; transfer_raw_index_t* tIndex_All = (transfer_raw_index_t*)AllocBlock(sizeof(transfer_index_t) * MAX_PATCHES); float* tRGBData_All = (float*)AllocBlock(sizeof(float[3]) * MAX_PATCHES); #else transfer_raw_index_t* tIndex; rgb_transfer_data_t* tRGBData; transfer_raw_index_t* tIndex_All = (transfer_raw_index_t*)AllocBlock(sizeof(transfer_index_t) * MAX_PATCHES); rgb_transfer_data_t* tRGBData_All = (rgb_transfer_data_t*)AllocBlock(sizeof(rgb_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; tRGBData = tRGBData_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; vec3_t transparency = {1.0,1.0,1.0}; #ifdef HLRAD_TRANSLUCENT bool useback; useback = false; #endif if (!g_CheckVisBit(i, j , transparency #ifdef HLRAD_TRANSPARENCY_CPP , fastfind_index #endif ) || (i == j)) { #ifdef HLRAD_TRANSLUCENT if (patch->translucent_b) { if (!CheckVisBitBackwards(i, j, backorigin, backnormal #ifdef HLRAD_HULLU , transparency #endif ) || (i==j)) { 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_one = (dot1 * dot2) / (dist * dist); // Inverse square falloff factoring angle between patch normals #ifdef HLRAD_TRANSWEIRDFIX #ifdef HLRAD_NOSWAP if (trans_one * patch2->area > 0.8f) { trans_one = 0.8f / patch2->area; } #else if (trans_one * area > 0.8f) { trans_one = 0.8f / area; } #endif #endif #ifdef HLRAD_ACCURATEBOUNCE if (dist < patch2->emitter_range - ON_EPSILON) { #ifdef HLRAD_ACCURATEBOUNCE_ALTERNATEORIGIN if (light_behind_surface) { trans_one = 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_one = frac * trans_one + (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_one *= patch2->exposure; #endif VectorFill(trans, trans_one); VectorMultiply(trans, transparency, trans); //hullu: add transparency effect #ifdef HLRAD_TRANSLUCENT if (patch->translucent_b) { if (useback) { for (int x = 0; x < 3; x++) { trans[x] = patch->translucent_v[x] * trans[x]; } } else { for (int x = 0; x < 3; x++) { trans[x] = (1 - patch->translucent_v[x]) * trans[x]; } } } #endif #ifdef HLRAD_RGBTRANSFIX #ifdef HLRAD_ACCURATEBOUNCE if (trans_one <= 0.0) { continue; } #else if (trans_one >= 0) #endif { #ifndef HLRAD_TRANSWEIRDFIX #ifdef HLRAD_NOSWAP send = trans_one * area; #else send = trans_one * patch2->area; #endif if (send > 0.4f) { #ifdef HLRAD_NOSWAP trans_one = 0.4f / area; #else trans_one = 0.4f / patch2->area; #endif send = 0.4f; VectorFill(trans, trans_one); VectorMultiply(trans, transparency, trans); } #endif /*HLRAD_TRANSWEIRDFIX*/ #ifndef HLRAD_TRANSNONORMALIZE total += send; #endif #else /*HLRAD_RGBTRANSFIX*/ #ifdef HLRAD_ACCURATEBOUNCE if (VectorAvg(trans) <= 0.0) { continue; } #else if (VectorAvg(trans) >= 0) #endif { /////////////////////////////////////////RED send = trans[0] * patch2->area; // Caps light from getting weird if (send > 0.4f) { trans[0] = 0.4f / patch2->area; send = 0.4f; } #ifndef HLRAD_TRANSNONORMALIZE total += send / 3.0f; #endif /////////////////////////////////////////GREEN send = trans[1] * patch2->area; // Caps light from getting weird if (send > 0.4f) { trans[1] = 0.4f / patch2->area; send = 0.4f; } #ifndef HLRAD_TRANSNONORMALIZE total += send / 3.0f; #endif /////////////////////////////////////////BLUE send = trans[2] * patch2->area; // Caps light from getting weird if (send > 0.4f) { trans[2] = 0.4f / patch2->area; send = 0.4f; } #ifndef HLRAD_TRANSNONORMALIZE total += send / 3.0f; #endif #endif /*HLRAD_RGBTRANSFIX*/ #ifdef HLRAD_TRANSFERDATA_COMPRESS VectorScale(trans, patch2 -> area, trans); #else // scale to 16 bit (black magic) #ifdef HLRAD_NOSWAP VectorScale(trans, patch2 -> area * INVERSE_TRANSFER_SCALE, trans); #else VectorScale(trans, area * INVERSE_TRANSFER_SCALE, trans); #endif /*HLRAD_NOSWAP*/ if (trans[0] >= TRANSFER_SCALE_MAX) { trans[0] = TRANSFER_SCALE_MAX; } if (trans[1] >= TRANSFER_SCALE_MAX) { trans[1] = TRANSFER_SCALE_MAX; } if (trans[2] >= TRANSFER_SCALE_MAX) { trans[2] = TRANSFER_SCALE_MAX; } #endif } #ifndef HLRAD_ACCURATEBOUNCE else { #if 0 Warning("transfer < 0 (%4.3f %4.3f %4.3f): 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[0], trans[1], trans[2], 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 VectorFill(trans,0.0); } #endif #ifdef HLRAD_TRANSFERDATA_COMPRESS VectorCopy(trans, tRGBData); *tIndex = j; tRGBData+=3; tIndex++; patch->iData++; #else VectorCopy(trans, *tRGBData); *tIndex = j; tRGBData++; tIndex++; patch->iData++; #endif count++; } // copy the transfers out if (patch->iData) { #ifdef HLRAD_TRANSFERDATA_COMPRESS unsigned data_size = patch->iData * vector_size[g_rgbtransfer_compress_type] + unused_size; #else unsigned data_size = patch->iData * sizeof(rgb_transfer_data_t); #endif patch->tRGBData = (rgb_transfer_data_t*)AllocBlock(data_size); patch->tIndex = CompressTransferIndicies(tIndex_All, patch->iData, &patch->iIndex); hlassume(patch->tRGBData != 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 // // 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; rgb_transfer_data_t* t1 = patch->tRGBData; float* t2 = tRGBData_All; float f[3]; for (x = 0; x < patch->iData; x++, t1+=vector_size[g_rgbtransfer_compress_type], t2+=3) { VectorScale( t2, total, f ); vector_compress (g_rgbtransfer_compress_type, t1, &f[0], &f[1], &f[2]); } #else unsigned x; rgb_transfer_data_t* t1 = patch->tRGBData; rgb_transfer_data_t* t2 = tRGBData_All; for (x = 0; x < patch->iData; x++, t1++, t2++) { VectorScale( *t2, total, *t1 ); } #endif } } } FreeBlock(tIndex_All); FreeBlock(tRGBData_All); ThreadLock(); g_total_transfer += count; ThreadUnlock(); } #ifdef SYSTEM_WIN32 #pragma warning(pop) #endif /* * ============= * SwapTransfersTask * * Change transfers from light sent out to light collected in. * In an ideal world, they would be exactly symetrical, but * because the form factors are only aproximated, then normalized, * they will actually be rather different. * ============= */ #ifndef HLRAD_NOSWAP void SwapRGBTransfers(const int patchnum) { patch_t* patch = &g_patches[patchnum]; transfer_index_t* tIndex = patch->tIndex; rgb_transfer_data_t* tRGBData= patch->tRGBData; unsigned x; for (x = 0; x < patch->iIndex; x++, tIndex++) { unsigned size = (tIndex->size + 1); unsigned patchnum2 = tIndex->index; unsigned y; for (y = 0; y < size; y++, tRGBData++, patchnum2++) { patch_t* patch2 = &g_patches[patchnum2]; if (patchnum2 > patchnum) { // done with this list return; } else if (!patch2->iData) { // Set to zero in this impossible case Log("patch2 has no iData\n"); VectorFill(*tRGBData, 0); continue; } else { transfer_index_t* tIndex2 = patch2->tIndex; rgb_transfer_data_t* tRGBData2 = patch2->tRGBData; int offset = FindTransferOffsetPatchnum(tIndex2, patch2, patchnum); if (offset >= 0) { rgb_transfer_data_t tmp; VectorCopy(*tRGBData, tmp) VectorCopy(tRGBData2[offset], *tRGBData); VectorCopy(tmp, tRGBData2[offset]); } else { // Set to zero in this impossible case Log("FindTransferOffsetPatchnum returned -1 looking for patch %d in patch %d's transfer lists\n", patchnum, patchnum2); VectorFill(*tRGBData, 0); return; } } } } }