12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450 |
- #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;
- bool g_light_remove = DEFAULT_OBS_LIGHT_REMOVAL;
- 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 * lNumAddress, int * lListAddress)
- {
- 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];
- }
- }
- //SILENCER-->
- //Strip light entities
- if(g_light_remove) {
- int i = 0;
- for (i = 0; i < *(lNumAddress); i++) {
- MarkEntityAsRedundant(&g_entities[*(lListAddress + i)]);
- }
- UnparseEntities();
- Log("Obsolete light entities removed: %i\n", i);
- } else {
- Log("Removal of obsolete lights disabled. Skipping.\n");
- }
- //<--SILENCER
- }
- // =====================================================================================
- // 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
|