/* ============= 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. ============= */ portal_t *GetNextPortal (void) { int j; portal_t *p, *tp; int min; int i; i = GetThreadWork (); // bump the pacifier if (i == -1) return NULL; ThreadLock(); min = 99999; p = NULL; for (j=0, tp = portals ; j<numportals*2 ; j++, tp++) { if (tp->nummightsee < min && tp->status == stat_none) { min = tp->nummightsee; p = tp; } } if (p) p->status = stat_working; ThreadUnlock(); return p; }
/* ============= GatherLight Get light from other patches Run multi-threaded ============= */ void GatherLight (int threadnum) { int j, k; transfer_t *trans; int num; patch_t *patch; vec3_t sum, v; while (1) { j = GetThreadWork (); if (j == -1) break; patch = &patches[j]; trans = patch->transfers; num = patch->numtransfers; VectorFill( sum, 0 ) for (k=0 ; k<num ; k++, trans++) { VectorScale( emitlight[trans->patch], trans->transfer, v ); VectorAdd( sum, v, sum ); } VectorCopy( sum, addlight[j] ); } }
static void ThreadWorkerFunction(int unused) { int work; while ((work = GetThreadWork()) != -1) { workfunction(work); } }
/* * ThreadWork * * Shared work entry point by all threads. Retrieve and perform * chunks of work iteratively until work is finished. */ static void ThreadWork(void *p){ int work; while(true){ work = GetThreadWork(); if(work == -1) break; WorkFunction(work); } }
/** * @brief Shared work entry point by all threads. Retrieve and perform * chunks of work iteratively until work is finished. */ static int ThreadWork (void *p) { while (qtrue) { int work = GetThreadWork(); if (work == -1) break; WorkFunction(work); } return 0; }
void RunThreadsOnIndividualThread(int threadnum) { int work; while (1) { work = GetThreadWork ( ); if (work == -1) break; workfunction(work); } }
void ThreadWorkerFunction(int threadnum) { int work; while (1) { work = GetThreadWork(); if (work == -1) break; // printf ("thread %i, work %i\n", threadnum, work); workfunction(work); } }
void ThreadWorkerFunction( int iThread, void *pUserData ) { int work; while (1) { work = GetThreadWork (); if (work == -1) break; workfunction( iThread, work ); } }
void ThreadWorkerFunction( int threadnum ){ int work; while ( 1 ) { work = GetThreadWork(); if ( work == -1 ) { break; } //Sys_FPrintf( SYS_VRB,"thread %i, work %i\n", threadnum, work); workfunction( work ); } }
static void * LightThread(void *junk) { int facenum; while (1) { facenum = GetThreadWork(); if (facenum == -1) return NULL; LightFace(facenum, nolightface[facenum], faceoffset[facenum]); } return NULL; }
// ===================================================================================== // 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)
static void ThreadComputeLeafAmbient( int iThread, void *pUserData ) { CUtlVector<ambientsample_t> list; while (1) { int leafID = GetThreadWork (); if (leafID == -1) break; list.RemoveAll(); ComputeAmbientForLeaf(iThread, leafID, list); // copy to the output array g_LeafAmbientSamples[leafID].SetCount( list.Count() ); for ( int i = 0; i < list.Count(); i++ ) { g_LeafAmbientSamples[leafID].Element(i) = list.Element(i); } } }
// AJM: MVD // ===================================================================================== // BlockVis // ===================================================================================== void BlockVis(int unused) { int i, j, k, l, m; portal_t *p; visblocker_t *v; visblocker_t *v2; leaf_t *leaf; while(1) { i = GetThreadWork(); if(i == -1) break; v = &g_visblockers[i]; // See which visblockers we need for(j = 0; j < v->numnames; j++) { // Find visblocker if(!(v2 = GetVisBlock(v->blocknames[j]))) continue; // For each leaf in v2, eliminate visibility from v1 for(k = 0; k < v->numleafs; k++) { leaf = &g_leafs[v->blockleafs[k]]; for(l = 0; l < leaf->numportals; l++) { p = leaf->portals[l]; for(m = 0; m < v2->numleafs; m++) { const unsigned offset = v2->blockleafs[m] >> 3; const unsigned bit = (1 << (v2->blockleafs[m] & 7)); p->mightsee[offset] &= ~bit; } } } } } }
void MakeScales (int threadnum) { int i; unsigned j; vec3_t delta; vec_t dist, scale; int count; float trans; patch_t *patch, *patch2; float total, send; dplane_t plane; vec3_t origin; vec_t area; transfer_t transfers[MAX_PATCHES], *all_transfers; count = 0; while (1) { i = GetThreadWork (); if (i == -1) break; patch = patches + i; total = 0; patch->numtransfers = 0; VectorCopy (patch->origin, origin); plane = *patch->plane; plane.dist = PatchPlaneDist( patch ); area = patch->area; // find out which patch2's will collect light // from patch all_transfers = transfers; for (j=0, patch2 = patches ; j<num_patches ; j++, patch2++) { if (!CheckVisBit (i, j)) continue; // calculate transferemnce VectorSubtract (patch2->origin, origin, delta); dist = VectorNormalize (delta); // skys don't care about the interface angle, but everything // else does if (!patch->sky) scale = DotProduct (delta, patch->normal); else scale = 1; scale *= -DotProduct (delta, patch2->normal); trans = scale / (dist*dist); if (trans < -ON_EPSILON) Error ("transfer < 0"); send = trans*patch2->area; if (send > 0.4f) { trans = 0.4f / patch2->area; send = 0.4f; } total += send; // scale to 16 bit trans = trans * area * INVERSE_TRANSFER_SCALE; if (trans >= 0x10000) trans = 0xffff; if (!trans) continue; all_transfers->transfer = (unsigned short)trans; all_transfers->patch = j; all_transfers++; patch->numtransfers++; count++; } // copy the transfers out if (patch->numtransfers) { transfer_t *t, *t2; patch->transfers = calloc (patch->numtransfers, sizeof(transfer_t)); if (!patch->transfers) Error ("Memory allocation failure"); // // normalize all transfers so exactly 50% of the light // is transfered to the surroundings // total = 0.5f/total; t = patch->transfers; t2 = transfers; for (j=0 ; j<(unsigned)patch->numtransfers ; j++, t++, t2++) { t->transfer = (unsigned short)(t2->transfer*total); t->patch = t2->patch; } } } ThreadLock (); total_transfer += count; ThreadUnlock (); }
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; } } } } }
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(); }