radial.cpp
来自「hl2 source code. Do not use it illegal.」· C++ 代码 · 共 891 行 · 第 1/2 页
CPP
891 行
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
//=============================================================================
#include "vrad.h"
#include "lightmap.h"
#include "radial.h"
#include <bumpvects.h>
#include "UtlRBTree.h"
#include "VMatrix.h"
#include "macro_texture.h"
void WorldToLuxelSpace( lightinfo_t const *l, Vector const &world, Vector2D &coord )
{
Vector pos;
VectorSubtract( world, l->luxelOrigin, pos );
coord[0] = DotProduct( pos, l->worldToLuxelSpace[0] ) - l->face->m_LightmapTextureMinsInLuxels[0];
coord[1] = DotProduct( pos, l->worldToLuxelSpace[1] ) - l->face->m_LightmapTextureMinsInLuxels[1];
}
void LuxelSpaceToWorld( lightinfo_t const *l, float s, float t, Vector &world )
{
Vector pos;
s += l->face->m_LightmapTextureMinsInLuxels[0];
t += l->face->m_LightmapTextureMinsInLuxels[1];
VectorMA( l->luxelOrigin, s, l->luxelToWorldSpace[0], pos );
VectorMA( pos, t, l->luxelToWorldSpace[1], world );
}
void AddDirectToRadial( radial_t *rad,
Vector const &pnt,
Vector2D const &coordmins, Vector2D const &coordmaxs,
Vector const light[NUM_BUMP_VECTS+1],
bool hasBumpmap, bool neighborHasBumpmap )
{
int s_min, s_max, t_min, t_max;
Vector2D coord;
int s, t;
float ds, dt;
float r;
float area;
int bumpSample;
// convert world pos into local lightmap texture coord
WorldToLuxelSpace( &rad->l, pnt, coord );
s_min = ( int )( coordmins[0] );
t_min = ( int )( coordmins[1] );
s_max = ( int )( coordmaxs[0] + 0.9999f ) + 1; // ????
t_max = ( int )( coordmaxs[1] + 0.9999f ) + 1;
s_min = max( s_min, 0 );
t_min = max( t_min, 0 );
s_max = min( s_max, rad->w );
t_max = min( t_max, rad->h );
for( s = s_min; s < s_max; s++ )
{
for( t = t_min; t < t_max; t++ )
{
float s0 = max( coordmins[0] - s, -1.0 );
float t0 = max( coordmins[1] - t, -1.0 );
float s1 = min( coordmaxs[0] - s, 1.0 );
float t1 = min( coordmaxs[1] - t, 1.0 );
area = (s1 - s0) * (t1 - t0);
if (area > EQUAL_EPSILON)
{
ds = fabs( coord[0] - s );
dt = fabs( coord[1] - t );
r = max( ds, dt );
if (r < 0.1)
{
r = area / 0.1;
}
else
{
r = area / r;
}
int i = s+t*rad->w;
if( hasBumpmap )
{
if( neighborHasBumpmap )
{
for( bumpSample = 0; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
VectorMA( rad->light[bumpSample][i], r, light[bumpSample], rad->light[bumpSample][i] );
}
}
else
{
VectorMA( rad->light[0][i], r, light[0], rad->light[0][i] );
for( bumpSample = 1; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
VectorMA( rad->light[bumpSample][i], r * OO_SQRT_3, light[0], rad->light[bumpSample][i] );
}
}
}
else
{
VectorMA( rad->light[0][i], r, light[0], rad->light[0][i] );
}
rad->weight[i] += r;
}
}
}
}
void AddBouncedToRadial( radial_t *rad,
Vector const &pnt,
Vector2D const &coordmins, Vector2D const &coordmaxs,
Vector const light[NUM_BUMP_VECTS+1],
bool hasBumpmap, bool neighborHasBumpmap )
{
int s_min, s_max, t_min, t_max;
Vector2D coord;
int s, t;
float ds, dt;
float r;
int bumpSample;
// convert world pos into local lightmap texture coord
WorldToLuxelSpace( &rad->l, pnt, coord );
float dists, distt;
dists = (coordmaxs[0] - coordmins[0]);
distt = (coordmaxs[1] - coordmins[1]);
// patches less than a luxel in size could be mistakeningly filtered, so clamp.
dists = max( 1.0, dists );
distt = max( 1.0, distt );
// find possible domain of patch influence
s_min = ( int )( coord[0] - dists * RADIALDIST );
t_min = ( int )( coord[1] - distt * RADIALDIST );
s_max = ( int )( coord[0] + dists * RADIALDIST + 1.0f );
t_max = ( int )( coord[1] + distt * RADIALDIST + 1.0f );
// clamp to valid luxel
s_min = max( s_min, 0 );
t_min = max( t_min, 0 );
s_max = min( s_max, rad->w );
t_max = min( t_max, rad->h );
for( s = s_min; s < s_max; s++ )
{
for( t = t_min; t < t_max; t++ )
{
// patch influence is based on patch size
ds = ( coord[0] - s ) / dists;
dt = ( coord[1] - t ) / distt;
r = RADIALDIST2 - (ds * ds + dt * dt);
int i = s+t*rad->w;
if (r > 0)
{
if( hasBumpmap )
{
if( neighborHasBumpmap )
{
for( bumpSample = 0; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
VectorMA( rad->light[bumpSample][i], r, light[bumpSample], rad->light[bumpSample][i] );
}
}
else
{
VectorMA( rad->light[0][i], r, light[0], rad->light[0][i] );
for( bumpSample = 1; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
VectorMA( rad->light[bumpSample][i], r * OO_SQRT_3, light[0], rad->light[bumpSample][i] );
}
}
}
else
{
VectorMA( rad->light[0][i], r, light[0], rad->light[0][i] );
}
rad->weight[i] += r;
}
}
}
}
void PatchLightmapCoordRange( radial_t *rad, int ndxPatch, Vector2D &mins, Vector2D &maxs )
{
winding_t *w;
int i;
Vector2D coord;
mins.Init( 1E30, 1E30 );
maxs.Init( -1E30, -1E30 );
patch_t *patch = &patches.Element( ndxPatch );
w = patch->winding;
for (i = 0; i < w->numpoints; i++)
{
WorldToLuxelSpace( &rad->l, w->p[i], coord );
mins[0] = min( mins[0], coord[0] );
maxs[0] = max( maxs[0], coord[0] );
mins[1] = min( mins[1], coord[1] );
maxs[1] = max( maxs[1], coord[1] );
}
}
radial_t *AllocateRadial( int facenum )
{
radial_t *rad;
rad = ( radial_t* )calloc( 1, sizeof( *rad ) );
rad->facenum = facenum;
InitLightinfo( &rad->l, facenum );
rad->w = rad->l.face->m_LightmapTextureSizeInLuxels[0]+1;
rad->h = rad->l.face->m_LightmapTextureSizeInLuxels[1]+1;
return rad;
}
void FreeRadial( radial_t *rad )
{
if (rad)
free( rad );
}
radial_t *BuildPatchRadial( int facenum )
{
int j;
radial_t *rad;
patch_t *patch;
faceneighbor_t *fn;
Vector2D mins, maxs;
Vector light[NUM_BUMP_VECTS+1];
int bumpSample;
bool needsBumpmap, neighborNeedsBumpmap;
needsBumpmap = texinfo[dfaces[facenum].texinfo].flags & SURF_BUMPLIGHT ? true : false;
rad = AllocateRadial( facenum );
fn = &faceneighbor[ rad->facenum ];
patch_t *pNextPatch;
if( facePatches.Element( rad->facenum ) != facePatches.InvalidIndex() )
{
for( patch = &patches.Element( facePatches.Element( rad->facenum ) ); patch; patch = pNextPatch )
{
// next patch
pNextPatch = NULL;
if( patch->ndxNext != patches.InvalidIndex() )
{
pNextPatch = &patches.Element( patch->ndxNext );
}
// skip patches with children
if (patch->child1 != patches.InvalidIndex() )
continue;
// get the range of patch lightmap texture coords
int ndxPatch = patch - patches.Base();
PatchLightmapCoordRange( rad, ndxPatch, mins, maxs );
if (patch->numtransfers == 0)
{
// Error, using patch that was never evaluated or has no samples
// patch->totallight[1] = 255;
}
VectorCopy( patch->totallight, light[0] );
for( bumpSample = 1; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
VectorCopy( patch->totallight, light[bumpSample] );
VectorScale( light[bumpSample], OO_SQRT_3, light[bumpSample] );
}
//
// displacement surface patch origin position and normal vectors have been changed to
// represent the displacement surface position and normal -- for radial "blending"
// we need to get the base surface patch origin!
//
if( ValidDispFace( &dfaces[facenum] ) )
{
Vector patchOrigin;
WindingCenter (patch->winding, patchOrigin );
AddBouncedToRadial( rad, patchOrigin, mins, maxs, light,
needsBumpmap, needsBumpmap );
}
else
{
AddBouncedToRadial( rad, patch->origin, mins, maxs, light,
needsBumpmap, needsBumpmap );
}
}
}
for (j=0 ; j<fn->numneighbors; j++)
{
if( facePatches.Element( fn->neighbor[j] ) != facePatches.InvalidIndex() )
{
for( patch = &patches.Element( facePatches.Element( fn->neighbor[j] ) ); patch; patch = pNextPatch )
{
// next patch
pNextPatch = NULL;
if( patch->ndxNext != patches.InvalidIndex() )
{
pNextPatch = &patches.Element( patch->ndxNext );
}
// skip patches with children
if (patch->child1 != patches.InvalidIndex() )
continue;
// get the range of patch lightmap texture coords
int ndxPatch = patch - patches.Base();
PatchLightmapCoordRange( rad, ndxPatch, mins, maxs );
neighborNeedsBumpmap = texinfo[dfaces[facenum].texinfo].flags & SURF_BUMPLIGHT ? true : false;
for( bumpSample = 0; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
VectorCopy( patch->totallight, light[bumpSample] );
}
//
// displacement surface patch origin position and normal vectors have been changed to
// represent the displacement surface position and normal -- for radial "blending"
// we need to get the base surface patch origin!
//
if( ValidDispFace( &dfaces[fn->neighbor[j]] ) )
{
Vector patchOrigin;
WindingCenter (patch->winding, patchOrigin );
AddBouncedToRadial( rad, patchOrigin, mins, maxs, light,
needsBumpmap, needsBumpmap );
}
else
{
AddBouncedToRadial( rad, patch->origin, mins, maxs, light,
needsBumpmap, needsBumpmap );
}
}
}
}
return rad;
}
radial_t *BuildLuxelRadial( int facenum, int style )
{
int j, k;
facelight_t *fl;
faceneighbor_t *fn;
radial_t *rad;
Vector light[NUM_BUMP_VECTS + 1];
int bumpSample;
Vector2D coordmins, coordmaxs;
fl = &facelight[facenum];
fn = &faceneighbor[facenum];
rad = AllocateRadial( facenum );
bool needsBumpmap = texinfo[dfaces[facenum].texinfo].flags & SURF_BUMPLIGHT ? true : false;
for (k=0 ; k<fl->numsamples ; k++)
{
if( needsBumpmap )
{
for( bumpSample = 0; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
VectorCopy( fl->light[style][bumpSample][k], light[bumpSample] );
}
}
else
{
VectorCopy( fl->light[style][0][k], light[0] );
}
AddDirectToRadial( rad, fl->sample[k].pos, fl->sample[k].mins, fl->sample[k].maxs, light, needsBumpmap, needsBumpmap );
}
for (j = 0; j < fn->numneighbors; j++)
{
fl = &facelight[fn->neighbor[j]];
bool neighborHasBumpmap = false;
if( texinfo[dfaces[fn->neighbor[j]].texinfo].flags & SURF_BUMPLIGHT )
{
neighborHasBumpmap = true;
}
int nstyle = 0;
// look for style that matches
if (dfaces[fn->neighbor[j]].styles[nstyle] != dfaces[facenum].styles[style])
{
for (nstyle = 1; nstyle < MAXLIGHTMAPS; nstyle++ )
if ( dfaces[fn->neighbor[j]].styles[nstyle] == dfaces[facenum].styles[style] )
break;
// if not found, skip this neighbor
if (nstyle >= MAXLIGHTMAPS)
continue;
}
lightinfo_t l;
InitLightinfo( &l, fn->neighbor[j] );
for (k=0 ; k<fl->numsamples ; k++)
{
if( neighborHasBumpmap )
{
for( bumpSample = 0; bumpSample < NUM_BUMP_VECTS + 1; bumpSample++ )
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?