コード例 #1
0
ファイル: qrad.c プロジェクト: jpiolho/halflife
/*
=============
CollectLight
=============
*/
void CollectLight( vec3_t total )
{
	unsigned i;
	patch_t	*patch;

	VectorFill( total, 0 );

	for (i=0, patch=patches ; i<num_patches ; i++, patch++)
	{
		// sky's never collect light, it is just dropped
		if (patch->sky)
		{
			VectorFill( emitlight[ i ], 0 );
			VectorFill( addlight[ i ], 0 );
			continue;
		}

		VectorAdd( patch->totallight, addlight[i], patch->totallight );
		VectorScale( addlight[i], TRANSFER_SCALE, emitlight[i] );
		VectorAdd( total, emitlight[i], total );
		VectorFill( addlight[ i ], 0 );
	}

	VectorScale( total, INVERSE_TRANSFER_SCALE, total );
}
コード例 #2
0
ファイル: ltface.c プロジェクト: Arkshine/HLEnhanced
/*
============
LightFace
============
*/
void LightFace (int surfnum)
{
    dface_t *f;
    lightinfo_t	l;
    int		s, t;
    int		i,j,c;
    vec3_t	total;
    int		size;
    int		lightmapwidth, lightmapsize;
    byte	*out;
    vec3_t	*light;
    int		w, h;
    int		clamp = 192;
    float	clampfactor = 0.75;

    if ( !clamp192 )
    {
        clamp = 255;
        clampfactor = 1.0;
    }

    f = dfaces + surfnum;

//
// some surfaces don't need lightmaps
//
    f->lightofs = -1;
    for (j=0 ; j<MAXLIGHTMAPS ; j++)
        f->styles[j] = 255;

    if ( texinfo[f->texinfo].flags & TEX_SPECIAL)
    {   // non-lit texture
        return;
    }

    memset (&l, 0, sizeof(l));
    l.surfnum = surfnum;
    l.face = f;

//
// rotate plane
//
    VectorCopy (dplanes[f->planenum].normal, l.facenormal);
    l.facedist = dplanes[f->planenum].dist;
    if (f->side)
    {
        VectorSubtract (vec3_origin, l.facenormal, l.facenormal);
        l.facedist = -l.facedist;
    }



    CalcFaceVectors (&l);
    CalcFaceExtents (&l);
    CalcPoints (&l);

    lightmapwidth = l.texsize[0]+1;

    size = lightmapwidth*(l.texsize[1]+1);
    if (size > SINGLEMAP)
        Error ("Bad lightmap size");

    for (i=0 ; i<MAXLIGHTMAPS ; i++)
        l.lightstyles[i] = 255;

//
// cast all lights
//
    l.numlightstyles = 0;
    for (i=0 ; i<numlightentities ; i++)
        SingleLightFace (&lightentities[i], &l);

    FixMinlight (&l);

    if (!l.numlightstyles)
    {   // no light hitting it
        return;
    }

//
// save out the values
//
    for (i=0 ; i <MAXLIGHTMAPS ; i++)
        f->styles[i] = l.lightstyles[i];

    if( hicolor )
        lightmapsize = size*l.numlightstyles*3;
    else
        lightmapsize = size * l.numlightstyles;

    out = GetFileSpace (lightmapsize);
    f->lightofs = out - filebase;

// extra filtering
    h = (l.texsize[1]+1)*2;
    w = (l.texsize[0]+1)*2;

    for (i=0 ; i< l.numlightstyles ; i++)
    {
        if (l.lightstyles[i] == 0xff)
            Error ("Wrote empty lightmap");
        light = l.lightmaps[i];
        c = 0;
        for (t=0 ; t<=l.texsize[1] ; t++)
        {
            for (s=0 ; s<=l.texsize[0] ; s++, c++)
            {
                if (extrasamples)
                {
#ifdef OLD_CODE
                    // filtered sample
                    VectorCopy( light[t*2*w+s*2], total );
                    VectorAdd( total, light[t*2*w+s*2+1], total );
                    VectorAdd( total, light[(t*2+1)*w+s*2], total );
                    VectorAdd( total, light[(t*2+1)*w+s*2+1], total );
                    VectorScale( total, 0.25, total );
#else
                    int	u, v;
                    float	weight[3][3] =
                    {
                        {  5,  9,  5 },
                        {  9, 16,  9 },
                        {  5,  9,  5 },
                    };
                    float	divisor = 0.0;
                    VectorFill(total,0);
                    for ( u = 0; u < 3; u++ )
                    {
                        for ( v = 0; v < 3; v++ )
                        {
                            if ( s+u-2>=0 && t+v-1>=0 && s+u-1 <= w && t+v-1 <= h)
                            {
                                vec3_t	sample;
                                VectorScale( light[((t*2)+(v-1))*w + ((s*2)+(u-1))], weight[u][v], sample );
                                divisor += weight[u][v];
                                VectorAdd( total, sample, total );
                            }
                        }
                    }
#endif
                    if ( divisor > 1.0 )
                        VectorScale( total, 1/divisor, total );
                    total[0] = max(total[0],0.0);
                    total[1] = max(total[1],0.0);
                    total[2] = max(total[2],0.0);
                }
                else
                    VectorCopy( light[ c ], total );

                // Scale
                VectorScale( total, rangescale, total );

                // Clamp
                if( hicolor )
                {
                    for( j=0; j<3; j++ )
                    {
                        total[ j ] *= clampfactor;

                        if( total[j] > clamp)
                            total[j] = clamp;
                        else if (total[j] < 0)
                            Error ("light < 0");

                        *out++ = (byte) total[j];
                    }
                }
                else
                {
                    int intensity = total[ 0 ] + total[ 1 ] + total[ 2 ];
                    if( intensity > 255 )
                        intensity = 255;
                    else if( intensity < 0 )
                        Error( "light < 0" );

                    *out++ = (byte) intensity;
                }
            }
        }
    }
}
コード例 #3
0
ファイル: mathutil.cpp プロジェクト: n00ner/XashXT
// =====================================================================================
//  TestSegmentAgainstOpaqueList
//      Returns true if the segment intersects an item in the opaque list
// =====================================================================================
bool            TestSegmentAgainstOpaqueList(const vec_t* p1, const vec_t* p2
#ifdef HLRAD_HULLU
        , vec3_t &scaleout
#endif
#ifdef HLRAD_OPAQUE_STYLE
        , int &opaquestyleout // light must convert to this style. -1 = no convert
#endif
                                            )
{
#ifdef HLRAD_OPAQUE_NODE
    int x;
#ifdef HLRAD_HULLU
    VectorFill (scaleout, 1.0);
#endif
#ifdef HLRAD_OPAQUE_STYLE
    opaquestyleout = -1;
#endif
    for (x = 0; x < g_opaque_face_count; x++)
    {
        if (!TestLineOpaque (g_opaque_face_list[x].modelnum, g_opaque_face_list[x].origin, p1, p2))
        {
            continue;
        }
#ifdef HLRAD_HULLU
        if (g_opaque_face_list[x].transparency)
        {
            VectorMultiply (scaleout, g_opaque_face_list[x].transparency_scale, scaleout);
            continue;
        }
#endif
#ifdef HLRAD_OPAQUE_STYLE
        if (g_opaque_face_list[x].style != -1 && (opaquestyleout == -1 || g_opaque_face_list[x].style == opaquestyleout))
        {
            opaquestyleout = g_opaque_face_list[x].style;
            continue;
        }
#endif
#ifdef HLRAD_HULLU
        VectorFill (scaleout, 0.0);
#endif
#ifdef HLRAD_OPAQUE_STYLE
        opaquestyleout = -1;
#endif
        return true;
    }
    return false;
#else /*HLRAD_OPAQUE_NODE*/
    unsigned        x;
    vec3_t          point;
    const dplane_t* plane;
    const Winding*  winding;
#ifdef HLRAD_TestSegmentAgainstOpaqueList_VL
    int				i;
    vec3_t			scale_one;
    vec3_t			direction;
    VectorSubtract (p1, p2, direction);
    VectorNormalize (direction);
#endif

#ifdef HLRAD_HULLU
    vec3_t	    scale = {1.0, 1.0, 1.0};
#endif
#ifdef HLRAD_POINT_IN_EDGE_FIX
    double		percentage;
#endif
#ifdef HLRAD_OPAQUE_STYLE
    opaquestyleout = -1;
#endif

#ifdef HLRAD_OPAQUE_RANGE
    bool intersects[MAX_OPAQUE_GROUP_COUNT];
    for (x = 0; x < g_opaque_group_count; x++)
    {
        intersects[x] =
            LineSegmentIntersectsBounds (p1, p2, g_opaque_group_list[x].mins, g_opaque_group_list[x].maxs);
    }
#endif
    for (x = 0; x < g_opaque_face_count; x++)
    {
#ifdef HLRAD_OPAQUE_RANGE
        if (intersects[g_opaque_face_list[x].groupnum] == 0)
            continue;
#endif
        plane = &g_opaque_face_list[x].plane;
        winding = g_opaque_face_list[x].winding;

#ifdef HLRAD_OPACITY // AJM
        l_opacity = g_opaque_face_list[x].l_opacity;
#endif
        if (intersect_linesegment_plane(plane, p1, p2, point))
        {
#if 0
            Log
            ("Ray from (%4.3f %4.3f %4.3f) to (%4.3f %4.3f %4.3f) hits plane at (%4.3f %4.3f %4.3f)\n Plane (%4.3f %4.3f %4.3f) %4.3f\n",
             p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], point[0], point[1], point[2], plane->normal[0],
             plane->normal[1], plane->normal[2], plane->dist);
#endif
#ifdef HLRAD_POINT_IN_EDGE_FIX
            if (point_in_winding_percentage(*winding, *plane, point, direction, percentage))
#else
            if (point_in_winding(*winding, *plane, point))
#endif
            {
#if 0
                Log("Ray from (%4.3f %4.3f %4.3f) to (%4.3f %4.3f %4.3f) blocked by face %u @ (%4.3f %4.3f %4.3f)\n",
                    p1[0], p1[1], p1[2],
                    p2[0], p2[1], p2[2], g_opaque_face_list[x].facenum, point[0], point[1], point[2]);
#endif

#ifdef HLRAD_HULLU
                if(g_opaque_face_list[x].transparency)
                {
#ifdef HLRAD_TestSegmentAgainstOpaqueList_VL
                    VectorCopy (g_opaque_face_list[x].transparency_scale, scale_one);
#endif
#ifdef HLRAD_POINT_IN_EDGE_FIX
                    if (percentage != 1.0)
                        for (i = 0; i < 3; ++i)
                            scale_one[i] = pow (scale_one[i], percentage);
#endif
#ifdef HLRAD_TestSegmentAgainstOpaqueList_VL
                    VectorMultiply(scale, scale_one, scale);
#else
                    VectorMultiply(scale, g_opaque_face_list[x].transparency_scale, scale);
#endif
                }
                else
                {
#ifdef HLRAD_OPAQUE_STYLE
                    if (g_opaque_face_list[x].style == -1 || opaquestyleout != -1 && g_opaque_face_list[x].style != opaquestyleout)
                    {
                        VectorCopy(vec3_origin, scaleout);
                        opaquestyleout = -1;
                        return true;
                    }
                    else
                    {
                        opaquestyleout = g_opaque_face_list[x].style;
                    }
#else
#ifdef HLRAD_TestSegmentAgainstOpaqueList_VL
                    VectorCopy(vec3_origin, scaleout);
#else
                    VectorCopy(scale, scaleout);
#endif
                    return true;
#endif
                }
#else
                return true;
#endif
            }
        }
    }

#ifdef HLRAD_HULLU
    VectorCopy(scale, scaleout);
    if(scaleout[0] < 0.01 && scaleout[1] < 0.01 && scaleout[2] < 0.01)
    {
        return true; //so much shadowing that result is same as with normal opaque face
    }
#endif

    return false;
#endif /*HLRAD_OPAQUE_NODE*/
}
コード例 #4
0
ファイル: vismatrixutil.cpp プロジェクト: emileb/XashXT
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;
                }
            }
        }
    }
}