1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437 |
- #include "qrad.h"
- edgeshare_t g_edgeshare[MAX_MAP_EDGES];
- vec3_t g_face_centroids[MAX_MAP_EDGES];
- bool g_sky_lighting_fix = DEFAULT_SKY_LIGHTING_FIX;
- extern bool g_warned_direct;
- #define TEXTURE_STEP 16.0
- // =====================================================================================
- // PairEdges
- // =====================================================================================
- void PairEdges()
- {
- int i, j, k;
- dface_t* f;
- edgeshare_t* e;
- memset(&g_edgeshare, 0, sizeof(g_edgeshare));
- f = g_dfaces;
- for (i = 0; i < g_numfaces; i++, f++)
- {
- for (j = 0; j < f->numedges; j++)
- {
- k = g_dsurfedges[f->firstedge + j];
- if (k < 0)
- {
- e = &g_edgeshare[-k];
- hlassert(e->faces[1] == NULL);
- e->faces[1] = f;
- }
- else
- {
- e = &g_edgeshare[k];
- hlassert(e->faces[0] == NULL);
- e->faces[0] = f;
- }
- if (e->faces[0] && e->faces[1]) {
- // determine if coplanar
- if (e->faces[0]->planenum == e->faces[1]->planenum) {
- e->coplanar = true;
- } else {
- // see if they fall into a "smoothing group" based on angle of the normals
- vec3_t normals[2];
- VectorCopy(getPlaneFromFace(e->faces[0])->normal, normals[0]);
- VectorCopy(getPlaneFromFace(e->faces[1])->normal, normals[1]);
- e->cos_normals_angle = DotProduct(normals[0], normals[1]);
- if (e->cos_normals_angle > (1.0 - NORMAL_EPSILON))
- {
- e->coplanar = true;
- }
- else if (g_smoothing_threshold > 0.0)
- {
- if (e->cos_normals_angle >= g_smoothing_threshold)
- {
- VectorAdd(normals[0], normals[1], e->interface_normal);
- VectorNormalize(e->interface_normal);
- }
- }
- }
- }
- }
- }
- }
- #define MAX_SINGLEMAP (18*18*4)
- typedef struct
- {
- vec_t* light;
- vec_t facedist;
- vec3_t facenormal;
- int numsurfpt;
- vec3_t surfpt[MAX_SINGLEMAP];
- vec3_t texorg;
- vec3_t worldtotex[2]; // s = (world - texorg) . worldtotex[0]
- vec3_t textoworld[2]; // world = texorg + s * textoworld[0]
- vec_t exactmins[2], exactmaxs[2];
- int texmins[2], texsize[2];
- int lightstyles[256];
- int surfnum;
- dface_t* face;
- }
- lightinfo_t;
- // =====================================================================================
- // TextureNameFromFace
- // =====================================================================================
- static const char* TextureNameFromFace(const dface_t* const f)
- {
- texinfo_t* tx;
- miptex_t* mt;
- int ofs;
- //
- // check for light emited by texture
- //
- tx = &g_texinfo[f->texinfo];
- ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[tx->miptex];
- mt = (miptex_t*)((byte*) g_dtexdata + ofs);
- return mt->name;
- }
- // =====================================================================================
- // CalcFaceExtents
- // Fills in s->texmins[] and s->texsize[]
- // also sets exactmins[] and exactmaxs[]
- // =====================================================================================
- static void CalcFaceExtents(lightinfo_t* l)
- {
- const int facenum = l->surfnum;
- dface_t* s;
- vec_t mins[2], maxs[2], val;
- int i, j, e;
- dvertex_t* v;
- texinfo_t* tex;
- s = l->face;
- mins[0] = mins[1] = 999999;
- maxs[0] = maxs[1] = -99999;
- tex = &g_texinfo[s->texinfo];
- for (i = 0; i < s->numedges; i++)
- {
- e = g_dsurfedges[s->firstedge + i];
- if (e >= 0)
- {
- v = g_dvertexes + g_dedges[e].v[0];
- }
- else
- {
- v = g_dvertexes + g_dedges[-e].v[1];
- }
- for (j = 0; j < 2; j++)
- {
- val = v->point[0] * tex->vecs[j][0] +
- v->point[1] * tex->vecs[j][1] + v->point[2] * tex->vecs[j][2] + tex->vecs[j][3];
- if (val < mins[j])
- {
- mins[j] = val;
- }
- if (val > maxs[j])
- {
- maxs[j] = val;
- }
- }
- }
- for (i = 0; i < 2; i++)
- {
- l->exactmins[i] = mins[i];
- l->exactmaxs[i] = maxs[i];
- mins[i] = floor(mins[i] / 16.0);
- maxs[i] = ceil(maxs[i] / 16.0);
- l->texmins[i] = mins[i];
- l->texsize[i] = maxs[i] - mins[i];
- }
- if (!(tex->flags & TEX_SPECIAL))
- {
- if ((l->texsize[0] > 16) || (l->texsize[1] > 16))
- {
- ThreadLock();
- PrintOnce("\nfor Face %d (texture %s) at ", s - g_dfaces, TextureNameFromFace(s));
- for (i = 0; i < s->numedges; i++)
- {
- e = g_dsurfedges[s->firstedge + i];
- if (e >= 0)
- {
- v = g_dvertexes + g_dedges[e].v[0];
- }
- else
- {
- v = g_dvertexes + g_dedges[-e].v[1];
- }
- VectorAdd(v->point, g_face_offset[facenum], v->point);
- Log("(%4.3f %4.3f %4.3f) ", v->point[0], v->point[1], v->point[2]);
- }
- Log("\n");
- Error( "Bad surface extents (%d x %d)\nCheck the file ZHLTProblems.html for a detailed explanation of this problem", l->texsize[0], l->texsize[1]);
- }
- }
- }
- // =====================================================================================
- // CalcFaceVectors
- // Fills in texorg, worldtotex. and textoworld
- // =====================================================================================
- static void CalcFaceVectors(lightinfo_t* l)
- {
- texinfo_t* tex;
- int i, j;
- vec3_t texnormal;
- vec_t distscale;
- vec_t dist, len;
- tex = &g_texinfo[l->face->texinfo];
- // convert from float to double
- for (i = 0; i < 2; i++)
- {
- for (j = 0; j < 3; j++)
- {
- l->worldtotex[i][j] = tex->vecs[i][j];
- }
- }
- // calculate a normal to the texture axis. points can be moved along this
- // without changing their S/T
- CrossProduct(tex->vecs[1], tex->vecs[0], texnormal);
- VectorNormalize(texnormal);
- // flip it towards plane normal
- distscale = DotProduct(texnormal, l->facenormal);
- if (distscale == 0.0)
- {
- const unsigned facenum = l->face - g_dfaces;
-
- ThreadLock();
- Log("Malformed face (%d) normal @ \n", facenum);
- Winding* w = new Winding(*l->face);
- {
- const unsigned numpoints = w->m_NumPoints;
- unsigned x;
- for (x=0; x<numpoints; x++)
- {
- VectorAdd(w->m_Points[x], g_face_offset[facenum], w->m_Points[x]);
- }
- }
- w->Print();
- delete w;
- ThreadUnlock();
- hlassume(false, assume_MalformedTextureFace);
- }
- if (distscale < 0)
- {
- distscale = -distscale;
- VectorSubtract(vec3_origin, texnormal, texnormal);
- }
- // distscale is the ratio of the distance along the texture normal to
- // the distance along the plane normal
- distscale = 1.0 / distscale;
- for (i = 0; i < 2; i++)
- {
- len = (float)VectorLength(l->worldtotex[i]);
- dist = DotProduct(l->worldtotex[i], l->facenormal);
- dist *= distscale;
- VectorMA(l->worldtotex[i], -dist, texnormal, l->textoworld[i]);
- VectorScale(l->textoworld[i], (1 / len) * (1 / len), l->textoworld[i]);
- }
- // calculate texorg on the texture plane
- for (i = 0; i < 3; i++)
- {
- l->texorg[i] = -tex->vecs[0][3] * l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i];
- }
- // project back to the face plane
- dist = DotProduct(l->texorg, l->facenormal) - l->facedist - DEFAULT_HUNT_OFFSET;
- dist *= distscale;
- VectorMA(l->texorg, -dist, texnormal, l->texorg);
- }
- // =====================================================================================
- // SetSurfFromST
- // =====================================================================================
- static void SetSurfFromST(const lightinfo_t* const l, vec_t* surf, const vec_t s, const vec_t t)
- {
- const int facenum = l->surfnum;
- int j;
- for (j = 0; j < 3; j++)
- {
- surf[j] = l->texorg[j] + l->textoworld[0][j] * s + l->textoworld[1][j] * t;
- }
- // Adjust for origin-based models
- VectorAdd(surf, g_face_offset[facenum], surf);
- }
- // =====================================================================================
- // FindSurfaceMidpoint
- // =====================================================================================
- static dleaf_t* FindSurfaceMidpoint(const lightinfo_t* const l, vec_t* midpoint)
- {
- int s, t;
- int w, h;
- vec_t starts, startt;
- vec_t us, ut;
- vec3_t broken_midpoint;
- vec3_t surface_midpoint;
- int inside_point_count;
- dleaf_t* last_valid_leaf = NULL;
- dleaf_t* leaf_mid;
- const int facenum = l->surfnum;
- const dface_t* f = g_dfaces + facenum;
- const dplane_t* p = getPlaneFromFace(f);
- const vec_t* face_delta = g_face_offset[facenum];
- h = l->texsize[1] + 1;
- w = l->texsize[0] + 1;
- starts = (float)l->texmins[0] * 16;
- startt = (float)l->texmins[1] * 16;
- // General case
- inside_point_count = 0;
- VectorClear(surface_midpoint);
- for (t = 0; t < h; t++)
- {
- for (s = 0; s < w; s++)
- {
- us = starts + s * TEXTURE_STEP;
- ut = startt + t * TEXTURE_STEP;
- SetSurfFromST(l, midpoint, us, ut);
- if ((leaf_mid = PointInLeaf(midpoint)) != g_dleafs)
- {
- if ((leaf_mid->contents != CONTENTS_SKY) && (leaf_mid->contents != CONTENTS_SOLID))
- {
- last_valid_leaf = leaf_mid;
- inside_point_count++;
- VectorAdd(surface_midpoint, midpoint, surface_midpoint);
- }
- }
- }
- }
- if (inside_point_count > 1)
- {
- vec_t tmp = 1.0 / inside_point_count;
- VectorScale(surface_midpoint, tmp, midpoint);
- //Verbose("Trying general at (%4.3f %4.3f %4.3f) %d\n", surface_midpoint[0], surface_midpoint[1], surface_midpoint[2], inside_point_count);
- if (
- (leaf_mid =
- HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET)))
- {
- //Verbose("general method succeeded at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
- return leaf_mid;
- }
- //Verbose("Tried general , failed at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
- }
- else if (inside_point_count == 1)
- {
- //Verbose("Returning single point from general\n");
- VectorCopy(surface_midpoint, midpoint);
- return last_valid_leaf;
- }
- else
- {
- //Verbose("general failed (no points)\n");
- }
- // Try harder
- inside_point_count = 0;
- VectorClear(surface_midpoint);
- for (t = 0; t < h; t++)
- {
- for (s = 0; s < w; s++)
- {
- us = starts + s * TEXTURE_STEP;
- ut = startt + t * TEXTURE_STEP;
- SetSurfFromST(l, midpoint, us, ut);
- leaf_mid =
- HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET);
- if (leaf_mid != g_dleafs)
- {
- last_valid_leaf = leaf_mid;
- inside_point_count++;
- VectorAdd(surface_midpoint, midpoint, surface_midpoint);
- }
- }
- }
- if (inside_point_count > 1)
- {
- vec_t tmp = 1.0 / inside_point_count;
- VectorScale(surface_midpoint, tmp, midpoint);
- if (
- (leaf_mid =
- HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET)))
- {
- //Verbose("best method succeeded at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
- return leaf_mid;
- }
- //Verbose("Tried best, failed at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
- }
- else if (inside_point_count == 1)
- {
- //Verbose("Returning single point from best\n");
- VectorCopy(surface_midpoint, midpoint);
- return last_valid_leaf;
- }
- else
- {
- //Verbose("best failed (no points)\n");
- }
- // Original broken code
- {
- vec_t mids = (l->exactmaxs[0] + l->exactmins[0]) / 2;
- vec_t midt = (l->exactmaxs[1] + l->exactmins[1]) / 2;
- SetSurfFromST(l, midpoint, mids, midt);
- if ((leaf_mid = PointInLeaf(midpoint)) != g_dleafs)
- {
- if ((leaf_mid->contents != CONTENTS_SKY) && (leaf_mid->contents != CONTENTS_SOLID))
- {
- return leaf_mid;
- }
- }
- VectorCopy(midpoint, broken_midpoint);
- //Verbose("Tried original method, failed at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
- }
- VectorCopy(broken_midpoint, midpoint);
- return HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET);
- }
- // =====================================================================================
- // SimpleNudge
- // Return vec_t in point only valid when function returns true
- // Use negative scales to push away from center instead
- // =====================================================================================
- static bool SimpleNudge(vec_t* const point, const lightinfo_t* const l, vec_t* const s, vec_t* const t, const vec_t delta)
- {
- const int facenum = l->surfnum;
- const dface_t* f = g_dfaces + facenum;
- const dplane_t* p = getPlaneFromFace(f);
- const vec_t* face_delta = g_face_offset[facenum];
- const int h = l->texsize[1] + 1;
- const int w = l->texsize[0] + 1;
- const vec_t half_w = (vec_t)(w - 1) / 2.0;
- const vec_t half_h = (vec_t)(h - 1) / 2.0;
- const vec_t s_vec = *s;
- const vec_t t_vec = *t;
- vec_t s1;
- vec_t t1;
- if (s_vec > half_w)
- {
- s1 = s_vec - delta;
- }
- else
- {
- s1 = s_vec + delta;
- }
- SetSurfFromST(l, point, s1, t_vec);
- if (HuntForWorld(point, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET))
- {
- *s = s1;
- return true;
- }
- if (t_vec > half_h)
- {
- t1 = t_vec - delta;
- }
- else
- {
- t1 = t_vec + delta;
- }
- SetSurfFromST(l, point, s_vec, t1);
- if (HuntForWorld(point, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET))
- {
- *t = t1;
- return true;
- }
- return false;
- }
- typedef enum
- {
- LightOutside, // Not lit
- LightShifted, // used HuntForWorld on 100% dark face
- LightShiftedInside, // moved to neighbhor on 2nd cleanup pass
- LightNormal, // Normally lit with no movement
- LightPulledInside, // Pulled inside by bleed code adjustments
- LightSimpleNudge, // A simple nudge 1/3 or 2/3 towards center along S or T axist
- LightSimpleNudgeEmbedded // A nudge either 1 full unit in each of S and T axis, or 1/3 or 2/3 AWAY from center
- }
- light_flag_t;
- // =====================================================================================
- // CalcPoints
- // For each texture aligned grid point, back project onto the plane
- // to get the world xyz value of the sample point
- // =====================================================================================
- static void CalcPoints(lightinfo_t* l)
- {
- const int facenum = l->surfnum;
- const dface_t* f = g_dfaces + facenum;
- const dplane_t* p = getPlaneFromFace(f);
- const vec_t* face_delta = g_face_offset[facenum];
- const eModelLightmodes lightmode = g_face_lightmode[facenum];
- const vec_t mids = (l->exactmaxs[0] + l->exactmins[0]) / 2;
- const vec_t midt = (l->exactmaxs[1] + l->exactmins[1]) / 2;
- const int h = l->texsize[1] + 1;
- const int w = l->texsize[0] + 1;
- const vec_t starts = (l->texmins[0] * 16);
- const vec_t startt = (l->texmins[1] * 16);
- light_flag_t LuxelFlags[MAX_SINGLEMAP];
- light_flag_t* pLuxelFlags;
- vec_t us, ut;
- vec_t* surf;
- vec3_t surface_midpoint;
- dleaf_t* leaf_mid;
- dleaf_t* leaf_surf;
- int s, t;
- int i;
- l->numsurfpt = w * h;
- memset(LuxelFlags, 0, sizeof(LuxelFlags));
- leaf_mid = FindSurfaceMidpoint(l, surface_midpoint);
- #if 0
- if (!leaf_mid)
- {
- Developer(DEVELOPER_LEVEL_FLUFF, "CalcPoints [face %d] (%4.3f %4.3f %4.3f) midpoint outside world\n",
- facenum, surface_midpoint[0], surface_midpoint[1], surface_midpoint[2]);
- }
- else
- {
- Developer(DEVELOPER_LEVEL_FLUFF, "FindSurfaceMidpoint [face %d] @ (%4.3f %4.3f %4.3f)\n",
- facenum, surface_midpoint[0], surface_midpoint[1], surface_midpoint[2]);
- }
- #endif
- // First pass, light normally, and pull any faces toward the center for bleed adjustment
- surf = l->surfpt[0];
- pLuxelFlags = LuxelFlags;
- for (t = 0; t < h; t++)
- {
- for (s = 0; s < w; s++, surf += 3, pLuxelFlags++)
- {
- vec_t original_s = us = starts + s * TEXTURE_STEP;
- vec_t original_t = ut = startt + t * TEXTURE_STEP;
- SetSurfFromST(l, surf, us, ut);
- leaf_surf = HuntForWorld(surf, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET);
- if (!leaf_surf)
- {
- // At first try a 1/3 and 2/3 distance to nearest in each S and T axis towards the face midpoint
- if (SimpleNudge(surf, l, &us, &ut, TEXTURE_STEP * (1.0 / 3.0)))
- {
- *pLuxelFlags = LightSimpleNudge;
- }
- else if (SimpleNudge(surf, l, &us, &ut, -TEXTURE_STEP * (1.0 / 3.0)))
- {
- *pLuxelFlags = LightSimpleNudge;
- }
- else if (SimpleNudge(surf, l, &us, &ut, TEXTURE_STEP * (2.0 / 3.0)))
- {
- *pLuxelFlags = LightSimpleNudge;
- }
- else if (SimpleNudge(surf, l, &us, &ut, -TEXTURE_STEP * (2.0 / 3.0)))
- {
- *pLuxelFlags = LightSimpleNudge;
- }
- // Next, if this is a model flagged with the 'Embedded' mode, try away from the facemid too
- else if (lightmode & eModelLightmodeEmbedded)
- {
- SetSurfFromST(l, surf, us, ut);
- if (SimpleNudge(surf, l, &us, &ut, TEXTURE_STEP))
- {
- *pLuxelFlags = LightSimpleNudgeEmbedded;
- continue;
- }
- if (SimpleNudge(surf, l, &us, &ut, -TEXTURE_STEP))
- {
- *pLuxelFlags = LightSimpleNudgeEmbedded;
- continue;
- }
- SetSurfFromST(l, surf, original_s, original_t);
- *pLuxelFlags = LightOutside;
- continue;
- }
- }
- if (!(lightmode & eModelLightmodeEmbedded))
- {
- // Pull the sample points towards the facemid if visibility is blocked
- // and the facemid is inside the world
- int nudge_divisor = max(max(w, h), 4);
- int max_nudge = nudge_divisor + 1;
- bool nudge_succeeded = false;
- vec_t nudge_s = (mids - us) / (vec_t)nudge_divisor;
- vec_t nudge_t = (midt - ut) / (vec_t)nudge_divisor;
- vec3_t transparency;
- // if a line can be traced from surf to facemid, the point is good
- for (i = 0; i < max_nudge; i++)
- {
- // Make sure we are "in the world"(Not the zero leaf)
- if (leaf_mid)
- {
- SetSurfFromST(l, surf, us, ut);
- leaf_surf =
- HuntForWorld(surf, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE,
- DEFAULT_HUNT_OFFSET);
- if (leaf_surf)
- {
- if (TestLine(surface_midpoint, surf) == CONTENTS_EMPTY)
- {
- if (lightmode & eModelLightmodeConcave)
- {
- #ifdef HLRAD_HULLU
- //removed reset of transparency - TestSegmentAgainstOpaqueList already resets to 1,1,1
- int blocking_facenum = TestSegmentAgainstOpaqueList(surface_midpoint, surf, transparency);
- #else
- int blocking_facenum = TestSegmentAgainstOpaqueList(surface_midpoint, surf);
- #endif
- if(blocking_facenum > -1 && blocking_facenum != facenum)
- {
- //Log("SDF::4\n");
- us += nudge_s;
- ut += nudge_t;
- continue; // Try nudge again, we hit an opaque face
- }
- }
- if (i)
- {
- *pLuxelFlags = LightPulledInside;
- }
- else
- {
- *pLuxelFlags = LightNormal;
- }
- nudge_succeeded = true;
- break;
- }
- }
- }
- else
- {
- leaf_surf = PointInLeaf(surf);
- if (leaf_surf != g_dleafs)
- {
- if ((leaf_surf->contents != CONTENTS_SKY) && (leaf_surf->contents != CONTENTS_SOLID))
- {
- *pLuxelFlags = LightNormal;
- nudge_succeeded = true;
- break;
- }
- }
- }
- us += nudge_s;
- ut += nudge_t;
- }
- if (!nudge_succeeded)
- {
- SetSurfFromST(l, surf, original_s, original_t);
- *pLuxelFlags = LightOutside;
- }
- }
- }
- }
- // 2nd Pass, find units that are not lit and try to move them one half or unit worth
- // in each direction and see if that is lit.
- // This handles 1 x N lightmaps which are all dark everywhere and have no frame of refernece
- // for a good center or directly lit areas
- surf = l->surfpt[0];
- pLuxelFlags = LuxelFlags;
- #if 0
- Developer(DEVELOPER_LEVEL_SPAM,
- "w (%d) h (%d) dim (%d) leafmid (%4.3f %4.3f %4.3f) plane normal (%4.3f) (%4.3f) (%4.3f) dist (%f)\n", w,
- h, w * h, surface_midpoint[0], surface_midpoint[1], surface_midpoint[2], p->normal[0], p->normal[1],
- p->normal[2], p->dist);
- #endif
- {
- int total_dark = 0;
- int total_adjusted = 0;
- for (t = 0; t < h; t++)
- {
- for (s = 0; s < w; s++, surf += 3, pLuxelFlags++)
- {
- if (!*pLuxelFlags)
- {
- #if 0
- Developer(DEVELOPER_LEVEL_FLUFF, "Dark (%d %d) (%4.3f %4.3f %4.3f)\n",
- s, t, surf[0], surf[1], surf[2]);
- #endif
- total_dark++;
- if (HuntForWorld(surf, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET))
- {
- #if 0
- Developer(DEVELOPER_LEVEL_FLUFF, "Shifted %d %d to (%4.3f %4.3f %4.3f)\n", s, t, surf[0],
- surf[1], surf[2]);
- #endif
- *pLuxelFlags = LightShifted;
- total_adjusted++;
- }
- else if (HuntForWorld(surf, face_delta, p, 101, 0.5, DEFAULT_HUNT_OFFSET))
- {
- #if 0
- Developer(DEVELOPER_LEVEL_FLUFF, "Shifted %d %d to (%4.3f %4.3f %4.3f)\n", s, t, surf[0],
- surf[1], surf[2]);
- #endif
- *pLuxelFlags = LightShifted;
- total_adjusted++;
- }
- }
- }
- }
- #if 0
- if (total_dark)
- {
- Developer(DEVELOPER_LEVEL_FLUFF, "Pass 2 : %d dark, %d corrected\n", total_dark, total_adjusted);
- }
- #endif
- }
- // 3rd Pass, find units that are not lit and move them towards neighbhors who are
- // Currently finds the first lit neighbhor and uses its data
- surf = l->surfpt[0];
- pLuxelFlags = LuxelFlags;
- {
- int total_dark = 0;
- int total_adjusted = 0;
- for (t = 0; t < h; t++)
- {
- for (s = 0; s < w; s++, surf += 3, pLuxelFlags++)
- {
- if (!*pLuxelFlags)
- {
- int x_min = max(0, s - 1);
- int x_max = min(w, s + 1);
- int y_min = max(0, t - 1);
- int y_max = min(t, t + 1);
- int x, y;
- #if 0
- Developer(DEVELOPER_LEVEL_FLUFF, "Point outside (%d %d) (%4.3f %4.3f %4.3f)\n",
- s, t, surf[0], surf[1], surf[2]);
- #endif
- total_dark++;
- for (x = x_min; x < x_max; x++)
- {
- for (y = y_min; y < y_max; y++)
- {
- if (*pLuxelFlags >= LightNormal)
- {
- dleaf_t* leaf;
- vec_t* other_surf = l->surfpt[0];
- other_surf += ((y * w) + x) * 3;
- leaf = PointInLeaf(other_surf);
- if ((leaf->contents != CONTENTS_SKY && leaf->contents != CONTENTS_SOLID))
- {
- *pLuxelFlags = LightShiftedInside;
- #if 0
- Developer(DEVELOPER_LEVEL_MESSAGE,
- "Nudged (%d %d) (%4.3f %4.3f %4.3f) to (%d %d) (%4.3f %4.3f %4.3f) \n",
- s, t, surf[0], surf[1], surf[2], x, y, other_surf[0], other_surf[1],
- other_surf[2]);
- #endif
- VectorCopy(other_surf, surf);
- total_adjusted++;
- goto found_it;
- }
- }
- }
- }
- }
- found_it:;
- }
- }
- #if 0
- if (total_dark)
- {
- Developer(DEVELOPER_LEVEL_FLUFF, "Pass 2 : %d dark, %d corrected\n", total_dark, total_adjusted);
- }
- #endif
- }
- }
- //==============================================================
- typedef struct
- {
- vec3_t pos;
- vec3_t light;
- }
- sample_t;
- typedef struct
- {
- int numsamples;
- sample_t* samples[MAXLIGHTMAPS];
- }
- facelight_t;
- static directlight_t* directlights[MAX_MAP_LEAFS];
- static facelight_t facelight[MAX_MAP_FACES];
- static int numdlights;
- #define DIRECT_SCALE 0.1f
- // =====================================================================================
- // CreateDirectLights
- // =====================================================================================
- void CreateDirectLights()
- {
- unsigned i;
- patch_t* p;
- directlight_t* dl;
- dleaf_t* leaf;
- int leafnum;
- entity_t* e;
- entity_t* e2;
- const char* name;
- const char* target;
- float angle;
- vec3_t dest;
- // AJM: coplaner lighting
- vec3_t temp_normal;
- numdlights = 0;
- //
- // surfaces
- //
- for (i = 0, p = g_patches; i < g_num_patches; i++, p++)
- {
- #ifdef ZHLT_TEXLIGHT
- if (VectorAvg(p->baselight) >= g_dlight_threshold) //LRC
- #else
- if (VectorAvg(p->totallight) >= g_dlight_threshold)
- #endif
- {
- numdlights++;
- dl = (directlight_t*)calloc(1, sizeof(directlight_t));
- VectorCopy(p->origin, dl->origin);
- leaf = PointInLeaf(dl->origin);
- leafnum = leaf - g_dleafs;
- dl->next = directlights[leafnum];
- directlights[leafnum] = dl;
- #ifdef ZHLT_TEXLIGHT
- dl->style = p->emitstyle; //LRC
- #endif
- dl->type = emit_surface;
- VectorCopy(getPlaneFromFaceNumber(p->faceNumber)->normal, dl->normal);
- #ifdef ZHLT_TEXLIGHT
- VectorCopy(p->baselight, dl->intensity); //LRC
- #else
- VectorCopy(p->totallight, dl->intensity);
- #endif
- VectorScale(dl->intensity, p->area, dl->intensity);
- VectorScale(dl->intensity, DIRECT_SCALE, dl->intensity);
-
- // --------------------------------------------------------------
- // Changes by Adam Foster - [email protected]
- // mazemaster's l33t backwards lighting (I still haven't a clue
- // what it's supposed to be for) :-)
- #ifdef HLRAD_WHOME
- if (g_softlight_hack[0] || g_softlight_hack[1] || g_softlight_hack[2])
- {
- numdlights++;
- dl = (directlight_t *) calloc(1, sizeof(directlight_t));
- VectorCopy(p->origin, dl->origin);
- leaf = PointInLeaf(dl->origin);
- leafnum = leaf - g_dleafs;
- dl->next = directlights[leafnum];
- directlights[leafnum] = dl;
- dl->type = emit_surface;
- VectorCopy(getPlaneFromFaceNumber(p->faceNumber)->normal, dl->normal);
- VectorScale(dl->normal, g_softlight_hack_distance, temp_normal);
- VectorAdd(dl->origin, temp_normal, dl->origin);
- VectorScale(dl->normal, -1, dl->normal);
- #ifdef ZHLT_TEXLIGHT
- VectorCopy(p->baselight, dl->intensity); //LRC
- #else
- VectorCopy(p->totallight, dl->intensity);
- #endif
- VectorScale(dl->intensity, p->area, dl->intensity);
- VectorScale(dl->intensity, DIRECT_SCALE, dl->intensity);
- dl->intensity[0] *= g_softlight_hack[0];
- dl->intensity[1] *= g_softlight_hack[1];
- dl->intensity[2] *= g_softlight_hack[2];
- }
- #endif
- // --------------------------------------------------------------
- }
- #ifdef ZHLT_TEXLIGHT
- //LRC VectorClear(p->totallight[0]);
- #else
- VectorClear(p->totallight);
- #endif
- }
- //
- // entities
- //
- for (i = 0; i < (unsigned)g_numentities; i++)
- {
- const char* pLight;
- double r, g, b, scaler;
- float l1;
- int argCnt;
- e = &g_entities[i];
- name = ValueForKey(e, "classname");
- if (strncmp(name, "light", 5))
- continue;
- numdlights++;
- dl = (directlight_t*)calloc(1, sizeof(directlight_t));
- GetVectorForKey(e, "origin", dl->origin);
- leaf = PointInLeaf(dl->origin);
- leafnum = leaf - g_dleafs;
- dl->next = directlights[leafnum];
- directlights[leafnum] = dl;
- dl->style = IntForKey(e, "style");
- #ifdef ZHLT_TEXLIGHT
- if (dl->style < 0)
- dl->style = -dl->style; //LRC
- #endif
- pLight = ValueForKey(e, "_light");
- // scanf into doubles, then assign, so it is vec_t size independent
- r = g = b = scaler = 0;
- argCnt = sscanf_s(pLight, "%lf %lf %lf %lf", &r, &g, &b, &scaler);
- dl->intensity[0] = (float)r;
- if (argCnt == 1)
- {
- // The R,G,B values are all equal.
- dl->intensity[1] = dl->intensity[2] = (float)r;
- }
- else if (argCnt == 3 || argCnt == 4)
- {
- // Save the other two G,B values.
- dl->intensity[1] = (float)g;
- dl->intensity[2] = (float)b;
- // Did we also get an "intensity" scaler value too?
- if (argCnt == 4)
- {
- // Scale the normalized 0-255 R,G,B values by the intensity scaler
- dl->intensity[0] = dl->intensity[0] / 255 * (float)scaler;
- dl->intensity[1] = dl->intensity[1] / 255 * (float)scaler;
- dl->intensity[2] = dl->intensity[2] / 255 * (float)scaler;
- }
- }
- else
- {
- Log("light at (%f,%f,%f) has bad or missing '_light' value : '%s'\n",
- dl->origin[0], dl->origin[1], dl->origin[2], pLight);
- continue;
- }
- dl->fade = FloatForKey(e, "_fade");
- if (dl->fade == 0.0)
- {
- dl->fade = g_fade;
- }
- dl->falloff = IntForKey(e, "_falloff");
- if (dl->falloff == 0)
- {
- dl->falloff = g_falloff;
- }
- target = ValueForKey(e, "target");
- if (!strcmp(name, "light_spot") || !strcmp(name, "light_environment") || target[0])
- {
- if (!VectorAvg(dl->intensity))
- {
- VectorFill(dl->intensity, 500);
- }
- dl->type = emit_spotlight;
- dl->stopdot = FloatForKey(e, "_cone");
- if (!dl->stopdot)
- {
- dl->stopdot = 10;
- }
- dl->stopdot2 = FloatForKey(e, "_cone2");
- if (!dl->stopdot2)
- {
- dl->stopdot2 = dl->stopdot;
- }
- if (dl->stopdot2 < dl->stopdot)
- {
- dl->stopdot2 = dl->stopdot;
- }
- dl->stopdot2 = (float)cos(dl->stopdot2 / 180 * Q_PI);
- dl->stopdot = (float)cos(dl->stopdot / 180 * Q_PI);
- if (target[0])
- { // point towards target
- e2 = FindTargetEntity(target);
- if (!e2)
- {
- Warning("light at (%i %i %i) has missing target",
- (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
- }
- else
- {
- GetVectorForKey(e2, "origin", dest);
- VectorSubtract(dest, dl->origin, dl->normal);
- VectorNormalize(dl->normal);
- }
- }
- else
- { // point down angle
- vec3_t vAngles;
- GetVectorForKey(e, "angles", vAngles);
- angle = (float)FloatForKey(e, "angle");
- if (angle == ANGLE_UP)
- {
- dl->normal[0] = dl->normal[1] = 0;
- dl->normal[2] = 1;
- }
- else if (angle == ANGLE_DOWN)
- {
- dl->normal[0] = dl->normal[1] = 0;
- dl->normal[2] = -1;
- }
- else
- {
- // if we don't have a specific "angle" use the "angles" YAW
- if (!angle)
- {
- angle = vAngles[1];
- }
- dl->normal[2] = 0;
- dl->normal[0] = (float)cos(angle / 180 * Q_PI);
- dl->normal[1] = (float)sin(angle / 180 * Q_PI);
- }
- angle = FloatForKey(e, "pitch");
- if (!angle)
- {
- // if we don't have a specific "pitch" use the "angles" PITCH
- angle = vAngles[0];
- }
- dl->normal[2] = (float)sin(angle / 180 * Q_PI);
- dl->normal[0] *= (float)cos(angle / 180 * Q_PI);
- dl->normal[1] *= (float)cos(angle / 180 * Q_PI);
- }
- if (FloatForKey(e, "_sky") || !strcmp(name, "light_environment"))
- {
- // -----------------------------------------------------------------------------------
- // Changes by Adam Foster - [email protected]
- // diffuse lighting hack - most of the following code nicked from earlier
- // need to get diffuse intensity from new _diffuse_light key
- //
- // What does _sky do for spotlights, anyway?
- // -----------------------------------------------------------------------------------
- #ifdef HLRAD_WHOME
- pLight = ValueForKey(e, "_diffuse_light");
- r = g = b = scaler = 0;
- argCnt = sscanf_s(pLight, "%lf %lf %lf %lf", &r, &g, &b, &scaler);
- dl->diffuse_intensity[0] = (float)r;
- if (argCnt == 1)
- {
- // The R,G,B values are all equal.
- dl->diffuse_intensity[1] = dl->diffuse_intensity[2] = (float)r;
- }
- else if (argCnt == 3 || argCnt == 4)
- {
- // Save the other two G,B values.
- dl->diffuse_intensity[1] = (float)g;
- dl->diffuse_intensity[2] = (float)b;
- // Did we also get an "intensity" scaler value too?
- if (argCnt == 4)
- {
- // Scale the normalized 0-255 R,G,B values by the intensity scaler
- dl->diffuse_intensity[0] = dl->diffuse_intensity[0] / 255 * (float)scaler;
- dl->diffuse_intensity[1] = dl->diffuse_intensity[1] / 255 * (float)scaler;
- dl->diffuse_intensity[2] = dl->diffuse_intensity[2] / 255 * (float)scaler;
- }
- }
- else
- {
- // backwards compatibility with maps without _diffuse_light
- dl->diffuse_intensity[0] = dl->intensity[0];
- dl->diffuse_intensity[1] = dl->intensity[1];
- dl->diffuse_intensity[2] = dl->intensity[2];
- }
- #endif
- // -----------------------------------------------------------------------------------
- dl->type = emit_skylight;
- dl->stopdot2 = FloatForKey(e, "_sky"); // hack stopdot2 to a sky key number
- }
- }
- else
- {
- if (!VectorAvg(dl->intensity))
- VectorFill(dl->intensity, 300);
- dl->type = emit_point;
- }
- if (dl->type != emit_skylight)
- {
- l1 = max(dl->intensity[0], max(dl->intensity[1], dl->intensity[2]));
- l1 = l1 * l1 / 10;
- dl->intensity[0] *= l1;
- dl->intensity[1] *= l1;
- dl->intensity[2] *= l1;
- }
- }
- hlassume(numdlights, assume_NoLights);
- Log("Direct lights: %i\n", numdlights);
- }
- // =====================================================================================
- // DeleteDirectLights
- // =====================================================================================
- void DeleteDirectLights()
- {
- int l;
- directlight_t* dl;
- for (l = 0; l < g_numleafs; l++)
- {
- dl = directlights[l];
- while (dl)
- {
- directlights[l] = dl->next;
- free(dl);
- dl = directlights[l];
- }
- }
- // AJM: todo: strip light entities out at this point
- }
- // =====================================================================================
- // GatherSampleLight
- // =====================================================================================
- #define NUMVERTEXNORMALS 162
- double r_avertexnormals[NUMVERTEXNORMALS][3] = {
- #include "../common/anorms.h"
- };
- static void GatherSampleLight(const int input_facenum, const vec3_t pos, const byte* const pvs, const vec3_t normal, vec3_t* sample, byte* styles)
- {
- int i;
- directlight_t* l;
- vec3_t add;
- vec3_t delta;
- #ifdef HLRAD_FASTMATH2
- const float LIGHT_EPSILON = ON_EPSILON;
- float dot;
- #else
- float dot, dot2;
- #endif
- float dist;
- float ratio;
- #ifdef HLRAD_OPACITY // AJM
- float l_opacity;
- #endif
- int style_index;
- directlight_t* sky_used = NULL;
- vec3_t transparency;
- for (i = 1; i < g_numleafs; i++)
- {
- l = directlights[i];
- if (l)
- {
- if (((l->type == emit_skylight) && (g_sky_lighting_fix)) || (pvs[(i - 1) >> 3] & (1 << ((i - 1) & 7))))
- {
- for (; l; l = l->next)
- {
- // skylights work fundamentally differently than normal lights
- if (l->type == emit_skylight)
- {
- // only allow one of each sky type to hit any given point
- if (sky_used)
- {
- continue;
- }
- sky_used = l;
- // make sure the angle is okay
- dot = -DotProduct(normal, l->normal);
- if (dot <= ON_EPSILON / 10)
- {
- continue;
- }
- // search back to see if we can hit a sky brush
- VectorScale(l->normal, -10000, delta);
- VectorAdd(pos, delta, delta);
- if (TestLine(pos, delta) != CONTENTS_SKY)
- {
- continue; // occluded
- }
- #ifdef HLRAD_HULLU
- //removed reset of transparency - TestSegmentAgainstOpaqueList already resets to 1,1,1
- int facenum = TestSegmentAgainstOpaqueList(pos, delta, transparency);
- #else
- int facenum = TestSegmentAgainstOpaqueList(pos, delta);
- #endif
- if(facenum > -1 && facenum != input_facenum)
- {
- continue;
- }
- VectorScale(l->intensity, dot, add);
- #ifdef HLRAD_HULLU
- VectorMultiply(add, transparency, add);
- #endif
- }
- #ifdef HLRAD_FASTMATH2
- else
- {
- VectorSubtract(l->origin,pos,delta);
- dist = min(1,VectorNormalize(delta)); //VectorNormalize returns old length
- dot = DotProduct(delta,normal);
- if(dot <= LIGHT_EPSILON) { continue; } //behind surface
- //calculate numberator factor caused by light type
- switch(l->type)
- {
- case emit_point:
- ratio = 1;
- break;
- case emit_surface:
- ratio = -DotProduct(delta,l->normal);
- if(ratio <= LIGHT_EPSILON) { continue; } //behind light surface
- break;
- case emit_spotlight:
- ratio = -DotProduct(delta,l->normal);
- if(ratio <= l->stopdot2) { continue; } //outside penumbra
- if(ratio <= l->stopdot) //between umbra and penumbra - scale it
- { ratio *= (ratio - l->stopdot2) / (l->stopdot - l->stopdot2); }
- break;
- default:
- hlassume(false, assume_BadLightType);
- break;
- }
- //primitive ratio (all types)
- ratio *= dot;
- ratio /= dist;
- //calculate denominator factor caused by light type
- switch(l->type)
- {
- case emit_point:
- case emit_spotlight:
- ratio /= l->fade;
- if(l->falloff == 2)
- { ratio /= dist; }
- break;
- case emit_surface:
- ratio /= g_fade;
- if(g_falloff == 2)
- { ratio /= dist; }
- break;
- }
- VectorScale(l->intensity, ratio, add);
- }
- #else
- else
- {
- float denominator;
- VectorSubtract(l->origin, pos, delta);
- dist = VectorNormalize(delta);
- dot = DotProduct(delta, normal);
- // if (dot <= 0.0)
- // continue;
- if (dot <= ON_EPSILON / 10)
- {
- continue; // behind sample surface
- }
- if (dist < 1.0)
- {
- dist = 1.0;
- }
- // Variable power falloff (1 = inverse linear, 2 = inverse square
- denominator = dist * l->fade;
- if (l->falloff == 2)
- {
- denominator *= dist;
- }
- switch (l->type)
- {
- case emit_point:
- {
- // Variable power falloff (1 = inverse linear, 2 = inverse square
- vec_t denominator = dist * l->fade;
- if (l->falloff == 2)
- {
- denominator *= dist;
- }
- ratio = dot / denominator;
- VectorScale(l->intensity, ratio, add);
- break;
- }
- case emit_surface:
- {
- dot2 = -DotProduct(delta, l->normal);
- if (dot2 <= ON_EPSILON / 10)
- {
- continue; // behind light surface
- }
- // Variable power falloff (1 = inverse linear, 2 = inverse square
- vec_t denominator = dist * g_fade;
- if (g_falloff == 2)
- {
- denominator *= dist;
- }
- ratio = dot * dot2 / denominator;
- VectorScale(l->intensity, ratio, add);
- break;
- }
- case emit_spotlight:
- {
- dot2 = -DotProduct(delta, l->normal);
- if (dot2 <= l->stopdot2)
- {
- continue; // outside light cone
- }
- // Variable power falloff (1 = inverse linear, 2 = inverse square
- vec_t denominator = dist * l->fade;
- if (l->falloff == 2)
- {
- denominator *= dist;
- }
- ratio = dot * dot2 / denominator;
- if (dot2 <= l->stopdot)
- {
- ratio *= (dot2 - l->stopdot2) / (l->stopdot - l->stopdot2);
- }
- VectorScale(l->intensity, ratio, add);
- break;
- }
- default:
- {
- hlassume(false, assume_BadLightType);
- break;
- }
- }
- }
- #endif
- if (VectorMaximum(add) > (l->style ? g_coring : 0))
- {
- #ifdef HLRAD_HULLU
- vec3_t transparency = {1.0,1.0,1.0};
- #endif
- if (l->type != emit_skylight && TestLine(pos, l->origin) != CONTENTS_EMPTY)
- {
- continue; // occluded
- }
- if (l->type != emit_skylight)
- { // Don't test from light_environment entities to face, the special sky code occludes correctly
- #ifdef HLRAD_HULLU
- int facenum = TestSegmentAgainstOpaqueList(pos, delta, transparency);
- #else
- int facenum = TestSegmentAgainstOpaqueList(pos, delta);
- #endif
- if(facenum > -1 && facenum != input_facenum)
- {
- continue;
- }
- }
- #ifdef HLRAD_OPACITY
- //VectorScale(add, l_opacity, add);
- #endif
- for (style_index = 0; style_index < MAXLIGHTMAPS; style_index++)
- {
- if (styles[style_index] == l->style || styles[style_index] == 255)
- {
- break;
- }
- }
- if (style_index == MAXLIGHTMAPS)
- {
- Warning("Too many direct light styles on a face(%f,%f,%f)", pos[0], pos[1], pos[2]);
- continue;
- }
- if (styles[style_index] == 255)
- {
- styles[style_index] = l->style;
- }
- #ifdef HLRAD_HULLU
- VectorMultiply(add,transparency,add);
- #endif
- VectorAdd(sample[style_index], add, sample[style_index]);
- }
- }
- }
- }
- }
- if (sky_used && g_indirect_sun != 0.0)
- {
- vec3_t total;
- int j;
- vec3_t sky_intensity;
- // -----------------------------------------------------------------------------------
- // Changes by Adam Foster - [email protected]
- // Instead of using intensity from sky_used->intensity, get it from the new sky_used->diffuse_intensity
- #ifdef HLRAD_WHOME
- VectorScale(sky_used->diffuse_intensity, g_indirect_sun / (NUMVERTEXNORMALS * 2), sky_intensity);
- #else
- VectorScale(sky_used->intensity, g_indirect_sun / (NUMVERTEXNORMALS * 2), sky_intensity);
- #endif
- // That should be it. Who knows - it might actually work!
- // AJM: It DOES actually work. Havent you ever heard of beta testing....
- // -----------------------------------------------------------------------------------
- total[0] = total[1] = total[2] = 0.0;
- for (j = 0; j < NUMVERTEXNORMALS; j++)
- {
- // make sure the angle is okay
- dot = -DotProduct(normal, r_avertexnormals[j]);
- if (dot <= ON_EPSILON / 10)
- {
- continue;
- }
- // search back to see if we can hit a sky brush
- VectorScale(r_avertexnormals[j], -10000, delta);
- VectorAdd(pos, delta, delta);
- if (TestLine(pos, delta) != CONTENTS_SKY)
- {
- continue; // occluded
- }
- VectorScale(sky_intensity, dot, add);
- VectorAdd(total, add, total);
- }
- if (VectorMaximum(total) > 0)
- {
- for (style_index = 0; style_index < MAXLIGHTMAPS; style_index++)
- {
- if (styles[style_index] == sky_used->style || styles[style_index] == 255)
- {
- break;
- }
- }
- if (style_index == MAXLIGHTMAPS)
- {
- Warning("Too many direct light styles on a face(%f,%f,%f)", pos[0], pos[1], pos[2]);
- return;
- }
- if (styles[style_index] == 255)
- {
- styles[style_index] = sky_used->style;
- }
- VectorAdd(sample[style_index], total, sample[style_index]);
- }
- }
- }
- // =====================================================================================
- // AddSampleToPatch
- // Take the sample's collected light and add it back into the apropriate patch for the radiosity pass.
- // =====================================================================================
- #ifdef ZHLT_TEXLIGHT
- static void AddSampleToPatch(const sample_t* const s, const int facenum, int style) //LRC
- #else
- static void AddSampleToPatch(const sample_t* const s, const int facenum)
- #endif
- {
- patch_t* patch;
- BoundingBox bounds;
- int i;
- if (g_numbounce == 0)
- {
- return;
- }
- for (patch = g_face_patches[facenum]; patch; patch = patch->next)
- {
- // see if the point is in this patch (roughly)
- patch->winding->getBounds(bounds);
- for (i = 0; i < 3; i++)
- {
- if (bounds.m_Mins[i] > s->pos[i] + 16)
- {
- goto nextpatch;
- }
- if (bounds.m_Maxs[i] < s->pos[i] - 16)
- {
- goto nextpatch;
- }
- }
- // add the sample to the patch
- #ifdef ZHLT_TEXLIGHT
- //LRC:
- for (i = 0; i < MAXLIGHTMAPS && patch->totalstyle[i] != 255; i++)
- {
- if (patch->totalstyle[i] == style)
- break;
- }
- if (i == MAXLIGHTMAPS)
- {
- if(!g_warned_direct || g_verbose)
- {
- Warning("Too many light styles on a face(%f,%f,%f)",patch->origin[0],patch->origin[1],patch->origin[2]);
- g_warned_direct = true;
- }
- }
- else
- {
- if (patch->totalstyle[i] == 255)
- {
- patch->totalstyle[i] = style;
- }
- patch->samples[i]++;
- VectorAdd(patch->samplelight[i], s->light, patch->samplelight[i]);
- }
- //LRC (ends)
- #else
- patch->samples++;
- VectorAdd(patch->samplelight, s->light, patch->samplelight);
- #endif
- //return;
- nextpatch:;
- }
- // don't worry if some samples don't find a patch
- }
- // =====================================================================================
- // GetPhongNormal
- // =====================================================================================
- void GetPhongNormal(int facenum, vec3_t spot, vec3_t phongnormal)
- {
- int j;
- const dface_t* f = g_dfaces + facenum;
- const dplane_t* p = getPlaneFromFace(f);
- vec3_t facenormal;
- VectorCopy(p->normal, facenormal);
- VectorCopy(facenormal, phongnormal);
- if (g_smoothing_threshold > 0.0)
- {
- // Calculate modified point normal for surface
- // Use the edge normals iff they are defined. Bend the surface towards the edge normal(s)
- // Crude first attempt: find nearest edge normal and do a simple interpolation with facenormal.
- // Second attempt: find edge points+center that bound the point and do a three-point triangulation(baricentric)
- // Better third attempt: generate the point normals for all vertices and do baricentric triangulation.
- for (j = 0; j < f->numedges; j++)
- {
- vec3_t p1;
- vec3_t p2;
- vec3_t v1;
- vec3_t v2;
- vec3_t vspot;
- unsigned prev_edge;
- unsigned next_edge;
- int e;
- int e1;
- int e2;
- edgeshare_t* es;
- edgeshare_t* es1;
- edgeshare_t* es2;
- float a1;
- float a2;
- float aa;
- float bb;
- float ab;
- if (j)
- {
- prev_edge = f->firstedge + ((j - 1) % f->numedges);
- }
- else
- {
- prev_edge = f->firstedge + f->numedges - 1;
- }
- if ((j + 1) != f->numedges)
- {
- next_edge = f->firstedge + ((j + 1) % f->numedges);
- }
- else
- {
- next_edge = f->firstedge;
- }
- e = g_dsurfedges[f->firstedge + j];
- e1 = g_dsurfedges[prev_edge];
- e2 = g_dsurfedges[next_edge];
- es = &g_edgeshare[abs(e)];
- es1 = &g_edgeshare[abs(e1)];
- es2 = &g_edgeshare[abs(e2)];
- if (
- (es->coplanar && es1->coplanar && es2->coplanar)
- ||
- (VectorCompare(es->interface_normal, vec3_origin) &&
- VectorCompare(es1->interface_normal, vec3_origin) &&
- VectorCompare(es2->interface_normal, vec3_origin)))
- {
- continue;
- }
- if (e > 0)
- {
- VectorCopy(g_dvertexes[g_dedges[e].v[0]].point, p1);
- VectorCopy(g_dvertexes[g_dedges[e].v[1]].point, p2);
- }
- else
- {
- VectorCopy(g_dvertexes[g_dedges[-e].v[1]].point, p1);
- VectorCopy(g_dvertexes[g_dedges[-e].v[0]].point, p2);
- }
- // Adjust for origin-based models
- VectorAdd(p1, g_face_offset[facenum], p1);
- VectorAdd(p2, g_face_offset[facenum], p2);
- // Build vectors from the middle of the face to the edge vertexes and the sample pos.
- VectorSubtract(p1, g_face_centroids[facenum], v1);
- VectorSubtract(p2, g_face_centroids[facenum], v2);
- VectorSubtract(spot, g_face_centroids[facenum], vspot);
- aa = DotProduct(v1, v1);
- bb = DotProduct(v2, v2);
- ab = DotProduct(v1, v2);
- a1 = (bb * DotProduct(v1, vspot) - ab * DotProduct(vspot, v2)) / (aa * bb - ab * ab);
- a2 = (DotProduct(vspot, v2) - a1 * ab) / bb;
- // Test center to sample vector for inclusion between center to vertex vectors (Use dot product of vectors)
- if (a1 >= 0.0 && a2 >= 0.0)
- {
- // calculate distance from edge to pos
- vec3_t n1, n2;
- vec3_t temp;
- VectorAdd(es->interface_normal, es1->interface_normal, n1);
- if (VectorCompare(n1, vec3_origin))
- {
- VectorCopy(facenormal, n1);
- }
- VectorNormalize(n1);
- VectorAdd(es->interface_normal, es2->interface_normal, n2);
- if (VectorCompare(n2, vec3_origin))
- {
- VectorCopy(facenormal, n2);
- }
- VectorNormalize(n2);
- // Interpolate between the center and edge normals based on sample position
- VectorScale(facenormal, 1.0 - a1 - a2, phongnormal);
- VectorScale(n1, a1, temp);
- VectorAdd(phongnormal, temp, phongnormal);
- VectorScale(n2, a2, temp);
- VectorAdd(phongnormal, temp, phongnormal);
- VectorNormalize(phongnormal);
- break;
- }
- }
- }
- }
- const vec3_t s_circuscolors[] = {
- {100000.0, 100000.0, 100000.0}, // white
- {100000.0, 0.0, 0.0 }, // red
- {0.0, 100000.0, 0.0 }, // green
- {0.0, 0.0, 100000.0}, // blue
- {0.0, 100000.0, 100000.0}, // cyan
- {100000.0, 0.0, 100000.0}, // magenta
- {100000.0, 100000.0, 0.0 } // yellow
- };
- // =====================================================================================
- // BuildFacelights
- // =====================================================================================
- void BuildFacelights(const int facenum)
- {
- dface_t* f;
- vec3_t sampled[MAXLIGHTMAPS];
- lightinfo_t l;
- int i;
- int j;
- int k;
- sample_t* s;
- vec_t* spot;
- patch_t* patch;
- const dplane_t* plane;
- byte pvs[(MAX_MAP_LEAFS + 7) / 8];
- int thisoffset = -1, lastoffset = -1;
- int lightmapwidth;
- int lightmapheight;
- int size;
- #ifdef HLRAD_HULLU
- bool b_transparency_loss = false;
- vec_t light_left_for_facelight = 1.0;
- #endif
- f = &g_dfaces[facenum];
- //
- // some surfaces don't need lightmaps
- //
- f->lightofs = -1;
- for (j = 0; j < MAXLIGHTMAPS; j++)
- {
- f->styles[j] = 255;
- }
- if (g_texinfo[f->texinfo].flags & TEX_SPECIAL)
- {
- return; // non-lit texture
- }
- f->styles[0] = 0; // Everyone gets the style zero map.
- memset(&l, 0, sizeof(l));
- l.surfnum = facenum;
- l.face = f;
- //
- // get transparency loss (part of light go through transparency faces.. reduce facelight on these)
- //
- #ifdef HLRAD_HULLU
- for(unsigned int m = 0; m < g_opaque_face_count; m++)
- {
- opaqueList_t* opaque = &g_opaque_face_list[m];
- if(opaque->facenum == facenum && opaque->transparency)
- {
- vec_t transparency = opaque->transparency;
-
- b_transparency_loss = true;
-
- light_left_for_facelight = 1.0 - transparency;
- if( light_left_for_facelight < 0.0 ) light_left_for_facelight = 0.0;
- if( light_left_for_facelight > 1.0 ) light_left_for_facelight = 1.0;
-
- break;
- }
- }
- #endif
- //
- // rotate plane
- //
- plane = getPlaneFromFace(f);
- VectorCopy(plane->normal, l.facenormal);
- l.facedist = plane->dist;
- CalcFaceVectors(&l);
- CalcFaceExtents(&l);
- CalcPoints(&l);
- lightmapwidth = l.texsize[0] + 1;
- lightmapheight = l.texsize[1] + 1;
- size = lightmapwidth * lightmapheight;
- hlassume(size <= MAX_SINGLEMAP, assume_MAX_SINGLEMAP);
- facelight[facenum].numsamples = l.numsurfpt;
- for (k = 0; k < MAXLIGHTMAPS; k++)
- {
- facelight[facenum].samples[k] = (sample_t*)calloc(l.numsurfpt, sizeof(sample_t));
- }
- spot = l.surfpt[0];
- for (i = 0; i < l.numsurfpt; i++, spot += 3)
- {
- vec3_t pointnormal = { 0, 0, 0 };
- for (k = 0; k < MAXLIGHTMAPS; k++)
- {
- VectorCopy(spot, facelight[facenum].samples[k][i].pos);
- }
- // get the PVS for the pos to limit the number of checks
- if (!g_visdatasize)
- {
- memset(pvs, 255, (g_numleafs + 7) / 8);
- lastoffset = -1;
- }
- else
- {
- dleaf_t* leaf = PointInLeaf(spot);
- thisoffset = leaf->visofs;
- if (i == 0 || thisoffset != lastoffset)
- {
- hlassert(thisoffset != -1);
- DecompressVis(&g_dvisdata[leaf->visofs], pvs, sizeof(pvs));
- }
- lastoffset = thisoffset;
- }
- memset(sampled, 0, sizeof(sampled));
- // If we are doing "extra" samples, oversample the direct light around the point.
- if (g_extra)
- {
- int weighting[3][3] = { {5, 9, 5}, {9, 16, 9}, {5, 9, 5} };
- vec3_t pos;
- int s, t, subsamples = 0;
- for (t = -1; t <= 1; t++)
- {
- for (s = -1; s <= 1; s++)
- {
- int subsample = i + t * lightmapwidth + s;
- int sample_s = i % lightmapwidth;
- int sample_t = i / lightmapwidth;
- if ((0 <= s + sample_s) && (s + sample_s < lightmapwidth)
- && (0 <= t + sample_t)&&(t + sample_t <lightmapheight))
- {
- vec3_t subsampled[MAXLIGHTMAPS];
- for (j = 0; j < MAXLIGHTMAPS; j++)
- {
- VectorFill(subsampled[j], 0);
- }
- // Calculate the point one third of the way toward the "subsample point"
- VectorCopy(l.surfpt[i], pos);
- VectorAdd(pos, l.surfpt[i], pos);
- VectorAdd(pos, l.surfpt[subsample], pos);
- VectorScale(pos, 1.0 / 3.0, pos);
- GetPhongNormal(facenum, pos, pointnormal);
- GatherSampleLight(facenum, pos, pvs, pointnormal, subsampled, f->styles);
- for (j = 0; j < MAXLIGHTMAPS && (f->styles[j] != 255); j++)
- {
- VectorScale(subsampled[j], weighting[s + 1][t + 1], subsampled[j]);
- VectorAdd(sampled[j], subsampled[j], sampled[j]);
- }
- subsamples += weighting[s + 1][t + 1];
- }
- }
- }
- for (j = 0; j < MAXLIGHTMAPS && (f->styles[j] != 255); j++)
- {
- VectorScale(sampled[j], 1.0 / subsamples, sampled[j]);
- }
- }
- else
- {
- GetPhongNormal(facenum, spot, pointnormal);
- GatherSampleLight(facenum, spot, pvs, pointnormal, sampled, f->styles);
- }
- for (j = 0; j < MAXLIGHTMAPS && (f->styles[j] != 255); j++)
- {
- VectorCopy(sampled[j], facelight[facenum].samples[j][i].light);
- #ifdef HLRAD_HULLU
- if(b_transparency_loss)
- {
- VectorScale(facelight[facenum].samples[j][i].light, light_left_for_facelight, facelight[facenum].samples[j][i].light);
- }
- #endif
- #ifdef ZHLT_TEXLIGHT
- AddSampleToPatch(&facelight[facenum].samples[j][i], facenum, f->styles[j]); //LRC
- #else
- if (f->styles[j] == 0)
- {
- AddSampleToPatch(&facelight[facenum].samples[j][i], facenum);
- }
- #endif
- }
- }
- // average up the direct light on each patch for radiosity
- if (g_numbounce > 0)
- {
- for (patch = g_face_patches[facenum]; patch; patch = patch->next)
- {
- #ifdef ZHLT_TEXLIGHT
- //LRC:
- unsigned istyle;
- for (istyle = 0; istyle < MAXLIGHTMAPS && patch->totalstyle[istyle] != 255; istyle++)
- {
- if (patch->samples[istyle])
- {
- vec3_t v; // BUGBUG: Use a weighted average instead?
- VectorScale(patch->samplelight[istyle], (1.0f / patch->samples[istyle]), v);
- VectorAdd(patch->totallight[istyle], v, patch->totallight[istyle]);
- VectorAdd(patch->directlight[istyle], v, patch->directlight[istyle]);
- }
- }
- //LRC (ends)
- #else
- if (patch->samples)
- {
- vec3_t v; // BUGBUG: Use a weighted average instead?
- VectorScale(patch->samplelight, (1.0f / patch->samples), v);
- VectorAdd(patch->totallight, v, patch->totallight);
- VectorAdd(patch->directlight, v, patch->directlight);
- }
- #endif
- }
- }
- // add an ambient term if desired
- if (g_ambient[0] || g_ambient[1] || g_ambient[2])
- {
- for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
- {
- if (f->styles[j] == 0)
- {
- s = facelight[facenum].samples[j];
- for (i = 0; i < l.numsurfpt; i++, s++)
- {
- VectorAdd(s->light, g_ambient, s->light);
- }
- break;
- }
- }
- }
- // add circus lighting for finding black lightmaps
- if (g_circus)
- {
- for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
- {
- if (f->styles[j] == 0)
- {
- int amt = 7;
- s = facelight[facenum].samples[j];
- while ((l.numsurfpt % amt) == 0)
- {
- amt--;
- }
- if (amt < 2)
- {
- amt = 7;
- }
- for (i = 0; i < l.numsurfpt; i++, s++)
- {
- if ((s->light[0] == 0) && (s->light[1] == 0) && (s->light[2] == 0))
- {
- VectorAdd(s->light, s_circuscolors[i % amt], s->light);
- }
- }
- break;
- }
- }
- }
- // light from dlight_threshold and above is sent out, but the
- // texture itself should still be full bright
- // if( VectorAvg( face_patches[facenum]->baselight ) >= dlight_threshold) // Now all lighted surfaces glow
- {
- #ifdef ZHLT_TEXLIGHT
- //LRC:
- if (g_face_patches[facenum])
- {
- for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
- {
- if (f->styles[j] == g_face_patches[facenum]->emitstyle) //LRC
- {
- break;
- }
- }
- if (j == MAXLIGHTMAPS)
- {
- if(!g_warned_direct || g_verbose)
- {
- Warning("Too many light styles on a face(%f,%f,%f)",g_face_patches[facenum]->origin[0],g_face_patches[facenum]->origin[1],g_face_patches[facenum]->origin[2]);
- g_warned_direct = true;
- }
- }
- else
- {
- if (f->styles[j] == 255)
- {
- f->styles[j] = g_face_patches[facenum]->emitstyle;
- }
- s = facelight[facenum].samples[j];
- for (i = 0; i < l.numsurfpt; i++, s++)
- {
- VectorAdd(s->light, g_face_patches[facenum]->baselight, s->light);
- }
- }
- }
- //LRC (ends)
- #else
- for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
- {
- if (f->styles[j] == 0)
- {
- if (g_face_patches[facenum])
- {
- s = facelight[facenum].samples[j];
- for (i = 0; i < l.numsurfpt; i++, s++)
- {
- VectorAdd(s->light, g_face_patches[facenum]->baselight, s->light);
- }
- break;
- }
- }
- }
- #endif
- }
- }
- // =====================================================================================
- // PrecompLightmapOffsets
- // =====================================================================================
- void PrecompLightmapOffsets()
- {
- int facenum;
- dface_t* f;
- facelight_t* fl;
- int lightstyles;
- #ifdef ZHLT_TEXLIGHT
- int i; //LRC
- patch_t* patch; //LRC
- #endif
- g_lightdatasize = 0;
- for (facenum = 0; facenum < g_numfaces; facenum++)
- {
- f = &g_dfaces[facenum];
- fl = &facelight[facenum];
- if (g_texinfo[f->texinfo].flags & TEX_SPECIAL)
- {
- continue; // non-lit texture
- }
- #ifdef ZHLT_TEXLIGHT
- //LRC - find all the patch lightstyles, and add them to the ones used by this face
- patch = g_face_patches[facenum];
- if (patch)
- {
- for (i = 0; i < MAXLIGHTMAPS && patch->totalstyle[i] != 255; i++)
- {
- for (lightstyles = 0; lightstyles < MAXLIGHTMAPS && f->styles[lightstyles] != 255; lightstyles++)
- {
- if (f->styles[lightstyles] == patch->totalstyle[i])
- break;
- }
- if (lightstyles == MAXLIGHTMAPS)
- {
- if(!g_warned_direct || g_verbose)
- {
- Warning("Too many direct light styles on a face(%f,%f,%f)",patch->origin[0],patch->origin[1],patch->origin[2]);
- g_warned_direct = true;
- }
- }
- else if (f->styles[lightstyles] == 255)
- {
- f->styles[lightstyles] = patch->totalstyle[i];
- // Log("Face acquires new lightstyle %d at offset %d\n", f->styles[lightstyles], lightstyles);
- }
- }
- }
- //LRC (ends)
- #endif
- for (lightstyles = 0; lightstyles < MAXLIGHTMAPS; lightstyles++)
- {
- if (f->styles[lightstyles] == 255)
- {
- break;
- }
- }
- if (!lightstyles)
- {
- continue;
- }
- f->lightofs = g_lightdatasize;
- g_lightdatasize += fl->numsamples * 3 * lightstyles;
- }
- }
- // =====================================================================================
- // FinalLightFace
- // Add the indirect lighting on top of the direct lighting and save into final map format
- // =====================================================================================
- void FinalLightFace(const int facenum)
- {
- int i, j, k;
- vec3_t lb, v;
- facelight_t* fl;
- sample_t* samp;
- float minlight;
- int lightstyles;
- dface_t* f;
- lerpTriangulation_t* trian = NULL;
- // ------------------------------------------------------------------------
- // Changes by Adam Foster - [email protected]
- #ifdef HLRAD_WHOME
- float temp_rand;
- #endif
- // ------------------------------------------------------------------------
- f = &g_dfaces[facenum];
- fl = &facelight[facenum];
- if (g_texinfo[f->texinfo].flags & TEX_SPECIAL)
- {
- return; // non-lit texture
- }
- for (lightstyles = 0; lightstyles < MAXLIGHTMAPS; lightstyles++)
- {
- if (f->styles[lightstyles] == 255)
- {
- break;
- }
- }
- if (!lightstyles)
- {
- return;
- }
- //
- // set up the triangulation
- //
- if (g_numbounce)
- {
- trian = CreateTriangulation(facenum);
- }
- //
- // sample the triangulation
- //
- minlight = FloatForKey(g_face_entity[facenum], "_minlight") * 128;
- hlassume(f->lightofs + fl->numsamples*lightstyles*3 < g_max_map_lightdata, assume_MAX_MAP_LIGHTING);
- for (k = 0; k < lightstyles; k++)
- {
- samp = fl->samples[k];
- for (j = 0; j < fl->numsamples; j++, samp++)
- {
- // Should be a VectorCopy, but we scale by 2 to compensate for an earlier lighting flaw
- // Specifically, the directlight contribution was included in the bounced light AND the directlight
- // Since many of the levels were built with this assumption, this "fudge factor" compensates for it.
- VectorScale(samp->light, g_direct_scale, lb);
- #ifdef ZHLT_TEXLIGHT
- if (g_numbounce)//LRC && (k == 0))
- {
- SampleTriangulation(trian, samp->pos, v, f->styles[k]); //LRC
- #else
- if (g_numbounce && (k == 0))
- {
- SampleTriangulation(trian, samp->pos, v);
- #endif
- if (isPointFinite(v))
- {
- VectorAdd(lb, v, lb);
- }
- else
- {
- Warning("point (%4.3f %4.3f %4.3f) infinite v (%4.3f %4.3f %4.3f)\n",
- samp->pos[0], samp->pos[1], samp->pos[2], v[0], v[1], v[2]);
- }
- }
- // ------------------------------------------------------------------------
- // Changes by Adam Foster - [email protected]
- // colour lightscale - code was originally:
- #ifdef HLRAD_WHOME
- lb[0] *= g_colour_lightscale[0];
- lb[1] *= g_colour_lightscale[1];
- lb[2] *= g_colour_lightscale[2];
- #else
- VectorScale(lb, g_lightscale, lb);
- #endif
- // ------------------------------------------------------------------------
- // clip from the bottom first
- for (i = 0; i < 3; i++)
- {
- if (lb[i] < minlight)
- {
- lb[i] = minlight;
- }
- }
- // clip from the top
- {
- vec_t max = VectorMaximum(lb);
- if (max > g_maxlight)
- {
- vec_t scale = g_maxlight / max;
- lb[0] *= scale;
- lb[1] *= scale;
- lb[2] *= scale;
- }
- }
- // ------------------------------------------------------------------------
- // Changes by Adam Foster - [email protected]
- #ifdef HLRAD_WHOME
- // AJM: your code is formatted really wierd, and i cant understand a damn thing.
- // so i reformatted it into a somewhat readable "normal" fashion. :P
- // colour gamma - code was originally:
- // if (g_qgamma != 1.0) {
- // for (i = 0; i < 3; i++) {
- // lb[i] = (float) pow(lb[i] / 256.0f, g_qgamma) * 256.0f;
- // }
- // }
- if ( g_colour_qgamma[0] != 1.0 )
- lb[0] = (float) pow(lb[0] / 256.0f, g_colour_qgamma[0]) * 256.0f;
- if ( g_colour_qgamma[1] != 1.0 )
- lb[1] = (float) pow(lb[1] / 256.0f, g_colour_qgamma[1]) * 256.0f;
- if ( g_colour_qgamma[2] != 1.0 )
- lb[2] = (float) pow(lb[2] / 256.0f, g_colour_qgamma[2]) * 256.0f;
- // Two different ways of adding noise to the lightmap - colour jitter
- // (red, green and blue channels are independent), and mono jitter
- // (monochromatic noise). For simulating dithering, on the cheap. :)
- // Tends to create seams between adjacent polygons, so not ideal.
- // Got really weird results when it was set to limit values to 256.0f - it
- // was as if r, g or b could wrap, going close to zero.
- if (g_colour_jitter_hack[0] || g_colour_jitter_hack[1] || g_colour_jitter_hack[2])
- {
- for (i = 0; i < 3; i++)
- {
- lb[i] += g_colour_jitter_hack[i] * ((float)rand() / RAND_MAX - 0.5);
- if (lb[i] < 0.0f)
- {
- lb[i] = 0.0f;
- }
- else if (lb[i] > 255.0f)
- {
- lb[i] = 255.0f;
- }
- }
- }
- if (g_jitter_hack[0] || g_jitter_hack[1] || g_jitter_hack[2])
- {
- temp_rand = (float)rand() / RAND_MAX - 0.5;
- for (i = 0; i < 3; i++)
- {
- lb[i] += g_jitter_hack[i] * temp_rand;
- if (lb[i] < 0.0f)
- {
- lb[i] = 0.0f;
- }
- else if (lb[i] > 255.0f)
- {
- lb[i] = 255.0f;
- }
- }
- }
- #else
- if (g_qgamma != 1.0) {
- for (i = 0; i < 3; i++) {
- lb[i] = (float) pow(lb[i] / 256.0f, g_qgamma) * 256.0f;
- }
- }
- #endif
- // ------------------------------------------------------------------------
- {
- unsigned char* colors = &g_dlightdata[f->lightofs + k * fl->numsamples * 3 + j * 3];
- colors[0] = (unsigned char)lb[0];
- colors[1] = (unsigned char)lb[1];
- colors[2] = (unsigned char)lb[2];
- }
- }
- }
- if (g_numbounce)
- {
- FreeTriangulation(trian);
- }
- }
- #ifdef ZHLT_TEXLIGHT
- //LRC
- vec3_t totallight_default = { 0, 0, 0 };
- //LRC - utility for getting the right totallight value from a patch
- vec3_t* GetTotalLight(patch_t* patch, int style)
- {
- int i;
- for (i = 0; i < MAXLIGHTMAPS && patch->totalstyle[i] != 255; i++)
- {
- if (patch->totalstyle[i] == style)
- return &(patch->totallight[i]);
- }
- return &totallight_default;
- }
- #endif
|