light.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // light.c
  19. #include "light.h"
  20. #ifdef _WIN32
  21. #ifdef _TTIMOBUILD
  22. #include "pakstuff.h"
  23. #else
  24. #include "../libs/pakstuff.h"
  25. #endif
  26. #endif
  27. #define EXTRASCALE 2
  28. typedef struct {
  29. float plane[4];
  30. vec3_t origin;
  31. vec3_t vectors[2];
  32. shaderInfo_t *si;
  33. } filter_t;
  34. #define MAX_FILTERS 1024
  35. filter_t filters[MAX_FILTERS];
  36. int numFilters;
  37. extern char source[1024];
  38. qboolean notrace;
  39. qboolean patchshadows;
  40. qboolean dump;
  41. qboolean extra;
  42. qboolean extraWide;
  43. qboolean lightmapBorder;
  44. qboolean noSurfaces;
  45. int samplesize = 16; //sample size in units
  46. int novertexlighting = 0;
  47. int nogridlighting = 0;
  48. // for run time tweaking of all area sources in the level
  49. float areaScale = 0.25;
  50. // for run time tweaking of all point sources in the level
  51. float pointScale = 7500;
  52. qboolean exactPointToPolygon = qtrue;
  53. float formFactorValueScale = 3;
  54. float linearScale = 1.0 / 8000;
  55. light_t *lights;
  56. int numPointLights;
  57. int numAreaLights;
  58. FILE *dumpFile;
  59. int c_visible, c_occluded;
  60. //int defaultLightSubdivide = 128; // vary by surface size?
  61. int defaultLightSubdivide = 999; // vary by surface size?
  62. vec3_t ambientColor;
  63. vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ];
  64. int entitySurface[ MAX_MAP_DRAW_SURFS ];
  65. // 7,9,11 normalized to avoid being nearly coplanar with common faces
  66. //vec3_t sunDirection = { 0.441835, 0.56807, 0.694313 };
  67. //vec3_t sunDirection = { 0.45, 0, 0.9 };
  68. //vec3_t sunDirection = { 0, 0, 1 };
  69. // these are usually overrided by shader values
  70. vec3_t sunDirection = { 0.45, 0.3, 0.9 };
  71. vec3_t sunLight = { 100, 100, 50 };
  72. typedef struct {
  73. dbrush_t *b;
  74. vec3_t bounds[2];
  75. } skyBrush_t;
  76. int numSkyBrushes;
  77. skyBrush_t skyBrushes[MAX_MAP_BRUSHES];
  78. /*
  79. the corners of a patch mesh will always be exactly at lightmap samples.
  80. The dimensions of the lightmap will be equal to the average length of the control
  81. mesh in each dimension divided by 2.
  82. The lightmap sample points should correspond to the chosen subdivision points.
  83. */
  84. /*
  85. ===============================================================
  86. SURFACE LOADING
  87. ===============================================================
  88. */
  89. #define MAX_FACE_POINTS 128
  90. /*
  91. ===============
  92. SubdivideAreaLight
  93. Subdivide area lights that are very large
  94. A light that is subdivided will never backsplash, avoiding weird pools of light near edges
  95. ===============
  96. */
  97. void SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal,
  98. float areaSubdivide, qboolean backsplash ) {
  99. float area, value, intensity;
  100. light_t *dl, *dl2;
  101. vec3_t mins, maxs;
  102. int axis;
  103. winding_t *front, *back;
  104. vec3_t planeNormal;
  105. float planeDist;
  106. if ( !w ) {
  107. return;
  108. }
  109. WindingBounds( w, mins, maxs );
  110. // check for subdivision
  111. for ( axis = 0 ; axis < 3 ; axis++ ) {
  112. if ( maxs[axis] - mins[axis] > areaSubdivide ) {
  113. VectorClear( planeNormal );
  114. planeNormal[axis] = 1;
  115. planeDist = ( maxs[axis] + mins[axis] ) * 0.5;
  116. ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back );
  117. SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse );
  118. SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse );
  119. FreeWinding( w );
  120. return;
  121. }
  122. }
  123. // create a light from this
  124. area = WindingArea (w);
  125. if ( area <= 0 || area > 20000000 ) {
  126. return;
  127. }
  128. numAreaLights++;
  129. dl = malloc(sizeof(*dl));
  130. memset (dl, 0, sizeof(*dl));
  131. dl->next = lights;
  132. lights = dl;
  133. dl->type = emit_area;
  134. WindingCenter( w, dl->origin );
  135. dl->w = w;
  136. VectorCopy ( normal, dl->normal);
  137. dl->dist = DotProduct( dl->origin, normal );
  138. value = ls->value;
  139. intensity = value * area * areaScale;
  140. VectorAdd( dl->origin, dl->normal, dl->origin );
  141. VectorCopy( ls->color, dl->color );
  142. dl->photons = intensity;
  143. // emitColor is irrespective of the area
  144. VectorScale( ls->color, value*formFactorValueScale*areaScale, dl->emitColor );
  145. dl->si = ls;
  146. if ( ls->contents & CONTENTS_FOG ) {
  147. dl->twosided = qtrue;
  148. }
  149. // optionally create a point backsplash light
  150. if ( backsplash && ls->backsplashFraction > 0 ) {
  151. dl2 = malloc(sizeof(*dl));
  152. memset (dl2, 0, sizeof(*dl2));
  153. dl2->next = lights;
  154. lights = dl2;
  155. dl2->type = emit_point;
  156. VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin );
  157. VectorCopy( ls->color, dl2->color );
  158. dl2->photons = dl->photons * ls->backsplashFraction;
  159. dl2->si = ls;
  160. }
  161. }
  162. /*
  163. ===============
  164. CountLightmaps
  165. ===============
  166. */
  167. void CountLightmaps( void ) {
  168. int count;
  169. int i;
  170. dsurface_t *ds;
  171. qprintf ("--- CountLightmaps ---\n");
  172. count = 0;
  173. for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
  174. // see if this surface is light emiting
  175. ds = &drawSurfaces[i];
  176. if ( ds->lightmapNum > count ) {
  177. count = ds->lightmapNum;
  178. }
  179. }
  180. count++;
  181. numLightBytes = count * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3;
  182. if ( numLightBytes > MAX_MAP_LIGHTING ) {
  183. Error("MAX_MAP_LIGHTING exceeded");
  184. }
  185. qprintf( "%5i drawSurfaces\n", numDrawSurfaces );
  186. qprintf( "%5i lightmaps\n", count );
  187. }
  188. /*
  189. ===============
  190. CreateSurfaceLights
  191. This creates area lights
  192. ===============
  193. */
  194. void CreateSurfaceLights( void ) {
  195. int i, j, side;
  196. dsurface_t *ds;
  197. shaderInfo_t *ls;
  198. winding_t *w;
  199. cFacet_t *f;
  200. light_t *dl;
  201. vec3_t origin;
  202. drawVert_t *dv;
  203. int c_lightSurfaces;
  204. float lightSubdivide;
  205. vec3_t normal;
  206. qprintf ("--- CreateSurfaceLights ---\n");
  207. c_lightSurfaces = 0;
  208. for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
  209. // see if this surface is light emiting
  210. ds = &drawSurfaces[i];
  211. ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
  212. if ( ls->value == 0 ) {
  213. continue;
  214. }
  215. // determine how much we need to chop up the surface
  216. if ( ls->lightSubdivide ) {
  217. lightSubdivide = ls->lightSubdivide;
  218. } else {
  219. lightSubdivide = defaultLightSubdivide;
  220. }
  221. c_lightSurfaces++;
  222. // an autosprite shader will become
  223. // a point light instead of an area light
  224. if ( ls->autosprite ) {
  225. // autosprite geometry should only have four vertexes
  226. if ( surfaceTest[i] ) {
  227. // curve or misc_model
  228. f = surfaceTest[i]->facets;
  229. if ( surfaceTest[i]->numFacets != 1 || f->numBoundaries != 4 ) {
  230. _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n",
  231. (int)f->points[0], (int)f->points[1], (int)f->points[2] );
  232. }
  233. VectorAdd( f->points[0], f->points[1], origin );
  234. VectorAdd( f->points[2], origin, origin );
  235. VectorAdd( f->points[3], origin, origin );
  236. VectorScale( origin, 0.25, origin );
  237. } else {
  238. // normal polygon
  239. dv = &drawVerts[ ds->firstVert ];
  240. if ( ds->numVerts != 4 ) {
  241. _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n",
  242. (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] );
  243. continue;
  244. }
  245. VectorAdd( dv[0].xyz, dv[1].xyz, origin );
  246. VectorAdd( dv[2].xyz, origin, origin );
  247. VectorAdd( dv[3].xyz, origin, origin );
  248. VectorScale( origin, 0.25, origin );
  249. }
  250. numPointLights++;
  251. dl = malloc(sizeof(*dl));
  252. memset (dl, 0, sizeof(*dl));
  253. dl->next = lights;
  254. lights = dl;
  255. VectorCopy( origin, dl->origin );
  256. VectorCopy( ls->color, dl->color );
  257. dl->photons = ls->value * pointScale;
  258. dl->type = emit_point;
  259. continue;
  260. }
  261. // possibly create for both sides of the polygon
  262. for ( side = 0 ; side <= ls->twoSided ; side++ ) {
  263. // create area lights
  264. if ( surfaceTest[i] ) {
  265. // curve or misc_model
  266. for ( j = 0 ; j < surfaceTest[i]->numFacets ; j++ ) {
  267. f = surfaceTest[i]->facets + j;
  268. w = AllocWinding( f->numBoundaries );
  269. w->numpoints = f->numBoundaries;
  270. memcpy( w->p, f->points, f->numBoundaries * 12 );
  271. VectorCopy( f->surface, normal );
  272. if ( side ) {
  273. winding_t *t;
  274. t = w;
  275. w = ReverseWinding( t );
  276. FreeWinding( t );
  277. VectorSubtract( vec3_origin, normal, normal );
  278. }
  279. SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue );
  280. }
  281. } else {
  282. // normal polygon
  283. w = AllocWinding( ds->numVerts );
  284. w->numpoints = ds->numVerts;
  285. for ( j = 0 ; j < ds->numVerts ; j++ ) {
  286. VectorCopy( drawVerts[ds->firstVert+j].xyz, w->p[j] );
  287. }
  288. VectorCopy( ds->lightmapVecs[2], normal );
  289. if ( side ) {
  290. winding_t *t;
  291. t = w;
  292. w = ReverseWinding( t );
  293. FreeWinding( t );
  294. VectorSubtract( vec3_origin, normal, normal );
  295. }
  296. SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue );
  297. }
  298. }
  299. }
  300. _printf( "%5i light emitting surfaces\n", c_lightSurfaces );
  301. }
  302. /*
  303. ================
  304. FindSkyBrushes
  305. ================
  306. */
  307. void FindSkyBrushes( void ) {
  308. int i, j;
  309. dbrush_t *b;
  310. skyBrush_t *sb;
  311. shaderInfo_t *si;
  312. dbrushside_t *s;
  313. // find the brushes
  314. for ( i = 0 ; i < numbrushes ; i++ ) {
  315. b = &dbrushes[i];
  316. for ( j = 0 ; j < b->numSides ; j++ ) {
  317. s = &dbrushsides[ b->firstSide + j ];
  318. if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) {
  319. sb = &skyBrushes[ numSkyBrushes ];
  320. sb->b = b;
  321. sb->bounds[0][0] = -dplanes[ dbrushsides[ b->firstSide + 0 ].planeNum ].dist - 1;
  322. sb->bounds[1][0] = dplanes[ dbrushsides[ b->firstSide + 1 ].planeNum ].dist + 1;
  323. sb->bounds[0][1] = -dplanes[ dbrushsides[ b->firstSide + 2 ].planeNum ].dist - 1;
  324. sb->bounds[1][1] = dplanes[ dbrushsides[ b->firstSide + 3 ].planeNum ].dist + 1;
  325. sb->bounds[0][2] = -dplanes[ dbrushsides[ b->firstSide + 4 ].planeNum ].dist - 1;
  326. sb->bounds[1][2] = dplanes[ dbrushsides[ b->firstSide + 5 ].planeNum ].dist + 1;
  327. numSkyBrushes++;
  328. break;
  329. }
  330. }
  331. }
  332. // default
  333. VectorNormalize( sunDirection, sunDirection );
  334. // find the sky shader
  335. for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
  336. si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader );
  337. if ( si->surfaceFlags & SURF_SKY ) {
  338. VectorCopy( si->sunLight, sunLight );
  339. VectorCopy( si->sunDirection, sunDirection );
  340. break;
  341. }
  342. }
  343. }
  344. /*
  345. =================================================================
  346. LIGHT SETUP
  347. =================================================================
  348. */
  349. /*
  350. ==================
  351. FindTargetEntity
  352. ==================
  353. */
  354. entity_t *FindTargetEntity( const char *target ) {
  355. int i;
  356. const char *n;
  357. for ( i = 0 ; i < num_entities ; i++ ) {
  358. n = ValueForKey (&entities[i], "targetname");
  359. if ( !strcmp (n, target) ) {
  360. return &entities[i];
  361. }
  362. }
  363. return NULL;
  364. }
  365. /*
  366. =============
  367. CreateEntityLights
  368. =============
  369. */
  370. void CreateEntityLights (void)
  371. {
  372. int i;
  373. light_t *dl;
  374. entity_t *e, *e2;
  375. const char *name;
  376. const char *target;
  377. vec3_t dest;
  378. const char *_color;
  379. float intensity;
  380. int spawnflags;
  381. //
  382. // entities
  383. //
  384. for ( i = 0 ; i < num_entities ; i++ ) {
  385. e = &entities[i];
  386. name = ValueForKey (e, "classname");
  387. if (strncmp (name, "light", 5))
  388. continue;
  389. numPointLights++;
  390. dl = malloc(sizeof(*dl));
  391. memset (dl, 0, sizeof(*dl));
  392. dl->next = lights;
  393. lights = dl;
  394. spawnflags = FloatForKey (e, "spawnflags");
  395. if ( spawnflags & 1 ) {
  396. dl->linearLight = qtrue;
  397. }
  398. GetVectorForKey (e, "origin", dl->origin);
  399. dl->style = FloatForKey (e, "_style");
  400. if (!dl->style)
  401. dl->style = FloatForKey (e, "style");
  402. if (dl->style < 0)
  403. dl->style = 0;
  404. intensity = FloatForKey (e, "light");
  405. if (!intensity)
  406. intensity = FloatForKey (e, "_light");
  407. if (!intensity)
  408. intensity = 300;
  409. _color = ValueForKey (e, "_color");
  410. if (_color && _color[0])
  411. {
  412. sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]);
  413. ColorNormalize (dl->color, dl->color);
  414. }
  415. else
  416. dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
  417. intensity = intensity * pointScale;
  418. dl->photons = intensity;
  419. dl->type = emit_point;
  420. // lights with a target will be spotlights
  421. target = ValueForKey (e, "target");
  422. if ( target[0] ) {
  423. float radius;
  424. float dist;
  425. e2 = FindTargetEntity (target);
  426. if (!e2) {
  427. _printf ("WARNING: light at (%i %i %i) has missing target\n",
  428. (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
  429. } else {
  430. GetVectorForKey (e2, "origin", dest);
  431. VectorSubtract (dest, dl->origin, dl->normal);
  432. dist = VectorNormalize (dl->normal, dl->normal);
  433. radius = FloatForKey (e, "radius");
  434. if ( !radius ) {
  435. radius = 64;
  436. }
  437. if ( !dist ) {
  438. dist = 64;
  439. }
  440. dl->radiusByDist = (radius + 16) / dist;
  441. dl->type = emit_spotlight;
  442. }
  443. }
  444. }
  445. }
  446. //=================================================================
  447. /*
  448. ================
  449. SetEntityOrigins
  450. Find the offset values for inline models
  451. ================
  452. */
  453. void SetEntityOrigins( void ) {
  454. int i, j;
  455. entity_t *e;
  456. vec3_t origin;
  457. const char *key;
  458. int modelnum;
  459. dmodel_t *dm;
  460. for ( i=0 ; i < num_entities ; i++ ) {
  461. e = &entities[i];
  462. key = ValueForKey (e, "model");
  463. if ( key[0] != '*' ) {
  464. continue;
  465. }
  466. modelnum = atoi( key + 1 );
  467. dm = &dmodels[ modelnum ];
  468. // set entity surface to true for all surfaces for this model
  469. for ( j = 0 ; j < dm->numSurfaces ; j++ ) {
  470. entitySurface[ dm->firstSurface + j ] = qtrue;
  471. }
  472. key = ValueForKey (e, "origin");
  473. if ( !key[0] ) {
  474. continue;
  475. }
  476. GetVectorForKey ( e, "origin", origin );
  477. // set origin for all surfaces for this model
  478. for ( j = 0 ; j < dm->numSurfaces ; j++ ) {
  479. VectorCopy( origin, surfaceOrigin[ dm->firstSurface + j ] );
  480. }
  481. }
  482. }
  483. /*
  484. =================================================================
  485. =================================================================
  486. */
  487. #define MAX_POINTS_ON_WINDINGS 64
  488. /*
  489. ================
  490. PointToPolygonFormFactor
  491. ================
  492. */
  493. float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ) {
  494. vec3_t triVector, triNormal;
  495. int i, j;
  496. vec3_t dirs[MAX_POINTS_ON_WINDING];
  497. float total;
  498. float dot, angle, facing;
  499. for ( i = 0 ; i < w->numpoints ; i++ ) {
  500. VectorSubtract( w->p[i], point, dirs[i] );
  501. VectorNormalize( dirs[i], dirs[i] );
  502. }
  503. // duplicate first vertex to avoid mod operation
  504. VectorCopy( dirs[0], dirs[i] );
  505. total = 0;
  506. for ( i = 0 ; i < w->numpoints ; i++ ) {
  507. j = i+1;
  508. dot = DotProduct( dirs[i], dirs[j] );
  509. // roundoff can cause slight creep, which gives an IND from acos
  510. if ( dot > 1.0 ) {
  511. dot = 1.0;
  512. } else if ( dot < -1.0 ) {
  513. dot = -1.0;
  514. }
  515. angle = acos( dot );
  516. CrossProduct( dirs[i], dirs[j], triVector );
  517. if ( VectorNormalize( triVector, triNormal ) < 0.0001 ) {
  518. continue;
  519. }
  520. facing = DotProduct( normal, triNormal );
  521. total += facing * angle;
  522. if ( total > 6.3 || total < -6.3 ) {
  523. static qboolean printed;
  524. if ( !printed ) {
  525. printed = qtrue;
  526. _printf( "WARNING: bad PointToPolygonFormFactor: %f at %1.1f %1.1f %1.1f from %1.1f %1.1f %1.1f\n", total,
  527. w->p[i][0], w->p[i][1], w->p[i][2], point[0], point[1], point[2]);
  528. }
  529. return 0;
  530. }
  531. }
  532. total /= 2*3.141592657; // now in the range of 0 to 1 over the entire incoming hemisphere
  533. return total;
  534. }
  535. /*
  536. ================
  537. FilterTrace
  538. Returns 0 to 1.0 filter fractions for the given trace
  539. ================
  540. */
  541. void FilterTrace( const vec3_t start, const vec3_t end, vec3_t filter ) {
  542. float d1, d2;
  543. filter_t *f;
  544. int filterNum;
  545. vec3_t point;
  546. float frac;
  547. int i;
  548. float s, t;
  549. int u, v;
  550. int x, y;
  551. byte *pixel;
  552. float radius;
  553. float len;
  554. vec3_t total;
  555. filter[0] = 1.0;
  556. filter[1] = 1.0;
  557. filter[2] = 1.0;
  558. for ( filterNum = 0 ; filterNum < numFilters ; filterNum++ ) {
  559. f = &filters[ filterNum ];
  560. // see if the plane is crossed
  561. d1 = DotProduct( start, f->plane ) - f->plane[3];
  562. d2 = DotProduct( end, f->plane ) - f->plane[3];
  563. if ( ( d1 < 0 ) == ( d2 < 0 ) ) {
  564. continue;
  565. }
  566. // calculate the crossing point
  567. frac = d1 / ( d1 - d2 );
  568. for ( i = 0 ; i < 3 ; i++ ) {
  569. point[i] = start[i] + frac * ( end[i] - start[i] );
  570. }
  571. VectorSubtract( point, f->origin, point );
  572. s = DotProduct( point, f->vectors[0] );
  573. t = 1.0 - DotProduct( point, f->vectors[1] );
  574. if ( s < 0 || s >= 1.0 || t < 0 || t >= 1.0 ) {
  575. continue;
  576. }
  577. // decide the filter size
  578. radius = 10 * frac;
  579. len = VectorLength( f->vectors[0] );
  580. if ( !len ) {
  581. continue;
  582. }
  583. radius = radius * len * f->si->width;
  584. // look up the filter, taking multiple samples
  585. VectorClear( total );
  586. for ( u = -1 ; u <= 1 ; u++ ) {
  587. for ( v = -1 ; v <=1 ; v++ ) {
  588. x = s * f->si->width + u * radius;
  589. if ( x < 0 ) {
  590. x = 0;
  591. }
  592. if ( x >= f->si->width ) {
  593. x = f->si->width - 1;
  594. }
  595. y = t * f->si->height + v * radius;
  596. if ( y < 0 ) {
  597. y = 0;
  598. }
  599. if ( y >= f->si->height ) {
  600. y = f->si->height - 1;
  601. }
  602. pixel = f->si->pixels + ( y * f->si->width + x ) * 4;
  603. total[0] += pixel[0];
  604. total[1] += pixel[1];
  605. total[2] += pixel[2];
  606. }
  607. }
  608. filter[0] *= total[0]/(255.0*9);
  609. filter[1] *= total[1]/(255.0*9);
  610. filter[2] *= total[2]/(255.0*9);
  611. }
  612. }
  613. /*
  614. ================
  615. SunToPoint
  616. Returns an amount of light to add at the point
  617. ================
  618. */
  619. int c_sunHit, c_sunMiss;
  620. void SunToPoint( const vec3_t origin, traceWork_t *tw, vec3_t addLight ) {
  621. int i;
  622. trace_t trace;
  623. skyBrush_t *b;
  624. vec3_t end;
  625. if ( !numSkyBrushes ) {
  626. VectorClear( addLight );
  627. return;
  628. }
  629. VectorMA( origin, MAX_WORLD_COORD * 2, sunDirection, end );
  630. TraceLine( origin, end, &trace, qtrue, tw );
  631. // see if trace.hit is inside a sky brush
  632. for ( i = 0 ; i < numSkyBrushes ; i++) {
  633. b = &skyBrushes[ i ];
  634. // this assumes that sky brushes are axial...
  635. if ( trace.hit[0] < b->bounds[0][0]
  636. || trace.hit[0] > b->bounds[1][0]
  637. || trace.hit[1] < b->bounds[0][1]
  638. || trace.hit[1] > b->bounds[1][1]
  639. || trace.hit[2] < b->bounds[0][2]
  640. || trace.hit[2] > b->bounds[1][2] ) {
  641. continue;
  642. }
  643. // trace again to get intermediate filters
  644. TraceLine( origin, trace.hit, &trace, qtrue, tw );
  645. // we hit the sky, so add sunlight
  646. if ( numthreads == 1 ) {
  647. c_sunHit++;
  648. }
  649. addLight[0] = trace.filter[0] * sunLight[0];
  650. addLight[1] = trace.filter[1] * sunLight[1];
  651. addLight[2] = trace.filter[2] * sunLight[2];
  652. return;
  653. }
  654. if ( numthreads == 1 ) {
  655. c_sunMiss++;
  656. }
  657. VectorClear( addLight );
  658. }
  659. /*
  660. ================
  661. SunToPlane
  662. ================
  663. */
  664. void SunToPlane( const vec3_t origin, const vec3_t normal, vec3_t color, traceWork_t *tw ) {
  665. float angle;
  666. vec3_t sunColor;
  667. if ( !numSkyBrushes ) {
  668. return;
  669. }
  670. angle = DotProduct( normal, sunDirection );
  671. if ( angle <= 0 ) {
  672. return; // facing away
  673. }
  674. SunToPoint( origin, tw, sunColor );
  675. VectorMA( color, angle, sunColor, color );
  676. }
  677. /*
  678. ================
  679. LightingAtSample
  680. ================
  681. */
  682. void LightingAtSample( vec3_t origin, vec3_t normal, vec3_t color,
  683. qboolean testOcclusion, qboolean forceSunLight, traceWork_t *tw ) {
  684. light_t *light;
  685. trace_t trace;
  686. float angle;
  687. float add;
  688. float dist;
  689. vec3_t dir;
  690. VectorCopy( ambientColor, color );
  691. // trace to all the lights
  692. for ( light = lights ; light ; light = light->next ) {
  693. //MrE: if the light is behind the surface
  694. if ( DotProduct(light->origin, normal) - DotProduct(normal, origin) < 0 )
  695. continue;
  696. // testing exact PTPFF
  697. if ( exactPointToPolygon && light->type == emit_area ) {
  698. float factor;
  699. float d;
  700. vec3_t pushedOrigin;
  701. // see if the point is behind the light
  702. d = DotProduct( origin, light->normal ) - light->dist;
  703. if ( !light->twosided ) {
  704. if ( d < -1 ) {
  705. continue; // point is behind light
  706. }
  707. }
  708. // test occlusion and find light filters
  709. // clip the line, tracing from the surface towards the light
  710. if ( !notrace && testOcclusion ) {
  711. TraceLine( origin, light->origin, &trace, qfalse, tw );
  712. // other light rays must not hit anything
  713. if ( trace.passSolid ) {
  714. continue;
  715. }
  716. } else {
  717. trace.filter[0] = 1.0;
  718. trace.filter[1] = 1.0;
  719. trace.filter[2] = 1.0;
  720. }
  721. // nudge the point so that it is clearly forward of the light
  722. // so that surfaces meeting a light emiter don't get black edges
  723. if ( d > -8 && d < 8 ) {
  724. VectorMA( origin, (8-d), light->normal, pushedOrigin );
  725. } else {
  726. VectorCopy( origin, pushedOrigin );
  727. }
  728. // calculate the contribution
  729. factor = PointToPolygonFormFactor( pushedOrigin, normal, light->w );
  730. if ( factor <= 0 ) {
  731. if ( light->twosided ) {
  732. factor = -factor;
  733. } else {
  734. continue;
  735. }
  736. }
  737. color[0] += factor * light->emitColor[0] * trace.filter[0];
  738. color[1] += factor * light->emitColor[1] * trace.filter[1];
  739. color[2] += factor * light->emitColor[2] * trace.filter[2];
  740. continue;
  741. }
  742. // calculate the amount of light at this sample
  743. if ( light->type == emit_point ) {
  744. VectorSubtract( light->origin, origin, dir );
  745. dist = VectorNormalize( dir, dir );
  746. // clamp the distance to prevent super hot spots
  747. if ( dist < 16 ) {
  748. dist = 16;
  749. }
  750. angle = DotProduct( normal, dir );
  751. if ( light->linearLight ) {
  752. add = angle * light->photons * linearScale - dist;
  753. if ( add < 0 ) {
  754. add = 0;
  755. }
  756. } else {
  757. add = light->photons / ( dist * dist ) * angle;
  758. }
  759. } else if ( light->type == emit_spotlight ) {
  760. float distByNormal;
  761. vec3_t pointAtDist;
  762. float radiusAtDist;
  763. float sampleRadius;
  764. vec3_t distToSample;
  765. float coneScale;
  766. VectorSubtract( light->origin, origin, dir );
  767. distByNormal = -DotProduct( dir, light->normal );
  768. if ( distByNormal < 0 ) {
  769. continue;
  770. }
  771. VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
  772. radiusAtDist = light->radiusByDist * distByNormal;
  773. VectorSubtract( origin, pointAtDist, distToSample );
  774. sampleRadius = VectorLength( distToSample );
  775. if ( sampleRadius >= radiusAtDist ) {
  776. continue; // outside the cone
  777. }
  778. if ( sampleRadius <= radiusAtDist - 32 ) {
  779. coneScale = 1.0; // fully inside
  780. } else {
  781. coneScale = ( radiusAtDist - sampleRadius ) / 32.0;
  782. }
  783. dist = VectorNormalize( dir, dir );
  784. // clamp the distance to prevent super hot spots
  785. if ( dist < 16 ) {
  786. dist = 16;
  787. }
  788. angle = DotProduct( normal, dir );
  789. add = light->photons / ( dist * dist ) * angle * coneScale;
  790. } else if ( light->type == emit_area ) {
  791. VectorSubtract( light->origin, origin, dir );
  792. dist = VectorNormalize( dir, dir );
  793. // clamp the distance to prevent super hot spots
  794. if ( dist < 16 ) {
  795. dist = 16;
  796. }
  797. angle = DotProduct( normal, dir );
  798. if ( angle <= 0 ) {
  799. continue;
  800. }
  801. angle *= -DotProduct( light->normal, dir );
  802. if ( angle <= 0 ) {
  803. continue;
  804. }
  805. if ( light->linearLight ) {
  806. add = angle * light->photons * linearScale - dist;
  807. if ( add < 0 ) {
  808. add = 0;
  809. }
  810. } else {
  811. add = light->photons / ( dist * dist ) * angle;
  812. }
  813. }
  814. if ( add <= 1.0 ) {
  815. continue;
  816. }
  817. // clip the line, tracing from the surface towards the light
  818. if ( !notrace && testOcclusion ) {
  819. TraceLine( origin, light->origin, &trace, qfalse, tw );
  820. // other light rays must not hit anything
  821. if ( trace.passSolid ) {
  822. continue;
  823. }
  824. } else {
  825. trace.filter[0] = 1;
  826. trace.filter[1] = 1;
  827. trace.filter[2] = 1;
  828. }
  829. // add the result
  830. color[0] += add * light->color[0] * trace.filter[0];
  831. color[1] += add * light->color[1] * trace.filter[1];
  832. color[2] += add * light->color[2] * trace.filter[2];
  833. }
  834. //
  835. // trace directly to the sun
  836. //
  837. if ( testOcclusion || forceSunLight ) {
  838. SunToPlane( origin, normal, color, tw );
  839. }
  840. }
  841. /*
  842. =============
  843. PrintOccluded
  844. For debugging
  845. =============
  846. */
  847. void PrintOccluded( byte occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE],
  848. int width, int height ) {
  849. int i, j;
  850. _printf( "\n" );
  851. for ( i = 0 ; i < height ; i++ ) {
  852. for ( j = 0 ; j < width ; j++ ) {
  853. _printf("%i", (int)occluded[j][i] );
  854. }
  855. _printf( "\n" );
  856. }
  857. }
  858. /*
  859. =============
  860. VertexLighting
  861. Vertex lighting will completely ignore occlusion, because
  862. shadows would not be resolvable anyway.
  863. =============
  864. */
  865. void VertexLighting( dsurface_t *ds, qboolean testOcclusion, qboolean forceSunLight, float scale, traceWork_t *tw ) {
  866. int i, j;
  867. drawVert_t *dv;
  868. vec3_t sample, normal;
  869. float max;
  870. VectorCopy( ds->lightmapVecs[2], normal );
  871. // generate vertex lighting
  872. for ( i = 0 ; i < ds->numVerts ; i++ ) {
  873. dv = &drawVerts[ ds->firstVert + i ];
  874. if ( ds->patchWidth ) {
  875. LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw );
  876. }
  877. else if (ds->surfaceType == MST_TRIANGLE_SOUP) {
  878. LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw );
  879. }
  880. else {
  881. LightingAtSample( dv->xyz, normal, sample, testOcclusion, forceSunLight, tw );
  882. }
  883. if (scale >= 0)
  884. VectorScale(sample, scale, sample);
  885. // clamp with color normalization
  886. max = sample[0];
  887. if ( sample[1] > max ) {
  888. max = sample[1];
  889. }
  890. if ( sample[2] > max ) {
  891. max = sample[2];
  892. }
  893. if ( max > 255 ) {
  894. VectorScale( sample, 255/max, sample );
  895. }
  896. // save the sample
  897. for ( j = 0 ; j < 3 ; j++ ) {
  898. if ( sample[j] > 255 ) {
  899. sample[j] = 255;
  900. }
  901. dv->color[j] = sample[j];
  902. }
  903. // Don't bother writing alpha since it will already be set to 255,
  904. // plus we don't want to write over alpha generated by SetTerrainTextures
  905. //dv->color[3] = 255;
  906. }
  907. }
  908. /*
  909. =================
  910. LinearSubdivideMesh
  911. For extra lighting, just midpoint one of the axis.
  912. The edges are clamped at the original edges.
  913. =================
  914. */
  915. mesh_t *LinearSubdivideMesh( mesh_t *in ) {
  916. int i, j;
  917. mesh_t *out;
  918. drawVert_t *v1, *v2, *vout;
  919. out = malloc( sizeof( *out ) );
  920. out->width = in->width * 2;
  921. out->height = in->height;
  922. out->verts = malloc( out->width * out->height * sizeof(*out->verts) );
  923. for ( j = 0 ; j < in->height ; j++ ) {
  924. out->verts[ j * out->width + 0 ] = in->verts[ j * in->width + 0 ];
  925. out->verts[ j * out->width + out->width - 1 ] = in->verts[ j * in->width + in->width - 1 ];
  926. for ( i = 1 ; i < out->width - 1 ; i+= 2 ) {
  927. v1 = in->verts + j * in->width + (i >> 1);
  928. v2 = v1 + 1;
  929. vout = out->verts + j * out->width + i;
  930. vout->xyz[0] = 0.75 * v1->xyz[0] + 0.25 * v2->xyz[0];
  931. vout->xyz[1] = 0.75 * v1->xyz[1] + 0.25 * v2->xyz[1];
  932. vout->xyz[2] = 0.75 * v1->xyz[2] + 0.25 * v2->xyz[2];
  933. vout->normal[0] = 0.75 * v1->normal[0] + 0.25 * v2->normal[0];
  934. vout->normal[1] = 0.75 * v1->normal[1] + 0.25 * v2->normal[1];
  935. vout->normal[2] = 0.75 * v1->normal[2] + 0.25 * v2->normal[2];
  936. VectorNormalize( vout->normal, vout->normal );
  937. vout++;
  938. vout->xyz[0] = 0.25 * v1->xyz[0] + 0.75 * v2->xyz[0];
  939. vout->xyz[1] = 0.25 * v1->xyz[1] + 0.75 * v2->xyz[1];
  940. vout->xyz[2] = 0.25 * v1->xyz[2] + 0.75 * v2->xyz[2];
  941. vout->normal[0] = 0.25 * v1->normal[0] + 0.75 * v2->normal[0];
  942. vout->normal[1] = 0.25 * v1->normal[1] + 0.75 * v2->normal[1];
  943. vout->normal[2] = 0.25 * v1->normal[2] + 0.75 * v2->normal[2];
  944. VectorNormalize( vout->normal, vout->normal );
  945. }
  946. }
  947. FreeMesh( in );
  948. return out;
  949. }
  950. /*
  951. ==============
  952. ColorToBytes
  953. ==============
  954. */
  955. void ColorToBytes( const float *color, byte *colorBytes ) {
  956. float max;
  957. vec3_t sample;
  958. VectorCopy( color, sample );
  959. // clamp with color normalization
  960. max = sample[0];
  961. if ( sample[1] > max ) {
  962. max = sample[1];
  963. }
  964. if ( sample[2] > max ) {
  965. max = sample[2];
  966. }
  967. if ( max > 255 ) {
  968. VectorScale( sample, 255/max, sample );
  969. }
  970. colorBytes[ 0 ] = sample[0];
  971. colorBytes[ 1 ] = sample[1];
  972. colorBytes[ 2 ] = sample[2];
  973. }
  974. /*
  975. =============
  976. TraceLtm
  977. =============
  978. */
  979. void TraceLtm( int num ) {
  980. dsurface_t *ds;
  981. int i, j, k;
  982. int x, y;
  983. int position, numPositions;
  984. vec3_t base, origin, normal;
  985. byte occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE];
  986. vec3_t color[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE];
  987. traceWork_t tw;
  988. vec3_t average;
  989. int count;
  990. mesh_t srcMesh, *mesh, *subdivided;
  991. shaderInfo_t *si;
  992. static float nudge[2][9] = {
  993. { 0, -1, 0, 1, -1, 1, -1, 0, 1 },
  994. { 0, -1, -1, -1, 0, 0, 1, 1, 1 }
  995. };
  996. int sampleWidth, sampleHeight, ssize;
  997. vec3_t lightmapOrigin, lightmapVecs[2];
  998. int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_WIDTH];
  999. ds = &drawSurfaces[num];
  1000. si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
  1001. // vertex-lit triangle model
  1002. if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
  1003. VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw );
  1004. return;
  1005. }
  1006. if ( ds->lightmapNum == -1 ) {
  1007. return; // doesn't need lighting at all
  1008. }
  1009. if (!novertexlighting) {
  1010. // calculate the vertex lighting for gouraud shade mode
  1011. VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw );
  1012. }
  1013. if ( ds->lightmapNum < 0 ) {
  1014. return; // doesn't need lightmap lighting
  1015. }
  1016. si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
  1017. ssize = samplesize;
  1018. if (si->lightmapSampleSize)
  1019. ssize = si->lightmapSampleSize;
  1020. if (si->patchShadows)
  1021. tw.patchshadows = qtrue;
  1022. else
  1023. tw.patchshadows = patchshadows;
  1024. if ( ds->surfaceType == MST_PATCH ) {
  1025. srcMesh.width = ds->patchWidth;
  1026. srcMesh.height = ds->patchHeight;
  1027. srcMesh.verts = drawVerts + ds->firstVert;
  1028. mesh = SubdivideMesh( srcMesh, 8, 999 );
  1029. PutMeshOnCurve( *mesh );
  1030. MakeMeshNormals( *mesh );
  1031. subdivided = RemoveLinearMeshColumnsRows( mesh );
  1032. FreeMesh(mesh);
  1033. mesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
  1034. if ( mesh->width != ds->lightmapWidth || mesh->height != ds->lightmapHeight ) {
  1035. Error( "Mesh lightmap miscount");
  1036. }
  1037. if ( extra ) {
  1038. mesh_t *mp;
  1039. // chop it up for more light samples (leaking memory...)
  1040. mp = mesh;//CopyMesh( mesh );
  1041. mp = LinearSubdivideMesh( mp );
  1042. mp = TransposeMesh( mp );
  1043. mp = LinearSubdivideMesh( mp );
  1044. mp = TransposeMesh( mp );
  1045. mesh = mp;
  1046. }
  1047. } else {
  1048. VectorCopy( ds->lightmapVecs[2], normal );
  1049. if ( !extra ) {
  1050. VectorCopy( ds->lightmapOrigin, lightmapOrigin );
  1051. VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] );
  1052. VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] );
  1053. } else {
  1054. // sample at a closer spacing for antialiasing
  1055. VectorCopy( ds->lightmapOrigin, lightmapOrigin );
  1056. VectorScale( ds->lightmapVecs[0], 0.5, lightmapVecs[0] );
  1057. VectorScale( ds->lightmapVecs[1], 0.5, lightmapVecs[1] );
  1058. VectorMA( lightmapOrigin, -0.5, lightmapVecs[0], lightmapOrigin );
  1059. VectorMA( lightmapOrigin, -0.5, lightmapVecs[1], lightmapOrigin );
  1060. }
  1061. }
  1062. if ( extra ) {
  1063. sampleWidth = ds->lightmapWidth * 2;
  1064. sampleHeight = ds->lightmapHeight * 2;
  1065. } else {
  1066. sampleWidth = ds->lightmapWidth;
  1067. sampleHeight = ds->lightmapHeight;
  1068. }
  1069. memset ( color, 0, sizeof( color ) );
  1070. // determine which samples are occluded
  1071. memset ( occluded, 0, sizeof( occluded ) );
  1072. for ( i = 0 ; i < sampleWidth ; i++ ) {
  1073. for ( j = 0 ; j < sampleHeight ; j++ ) {
  1074. if ( ds->patchWidth ) {
  1075. numPositions = 9;
  1076. VectorCopy( mesh->verts[j*mesh->width+i].normal, normal );
  1077. // VectorNormalize( normal, normal );
  1078. // push off of the curve a bit
  1079. VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base );
  1080. MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] );
  1081. } else {
  1082. numPositions = 9;
  1083. for ( k = 0 ; k < 3 ; k++ ) {
  1084. base[k] = lightmapOrigin[k] + normal[k]
  1085. + i * lightmapVecs[0][k]
  1086. + j * lightmapVecs[1][k];
  1087. }
  1088. }
  1089. VectorAdd( base, surfaceOrigin[ num ], base );
  1090. // we may need to slightly nudge the sample point
  1091. // if directly on a wall
  1092. for ( position = 0 ; position < numPositions ; position++ ) {
  1093. // calculate lightmap sample position
  1094. for ( k = 0 ; k < 3 ; k++ ) {
  1095. origin[k] = base[k] +
  1096. + ( nudge[0][position]/16 ) * lightmapVecs[0][k]
  1097. + ( nudge[1][position]/16 ) * lightmapVecs[1][k];
  1098. }
  1099. if ( notrace ) {
  1100. break;
  1101. }
  1102. if ( !PointInSolid( origin ) ) {
  1103. break;
  1104. }
  1105. }
  1106. // if none of the nudges worked, this sample is occluded
  1107. if ( position == numPositions ) {
  1108. occluded[i][j] = qtrue;
  1109. if ( numthreads == 1 ) {
  1110. c_occluded++;
  1111. }
  1112. continue;
  1113. }
  1114. if ( numthreads == 1 ) {
  1115. c_visible++;
  1116. }
  1117. occluded[i][j] = qfalse;
  1118. LightingAtSample( origin, normal, color[i][j], qtrue, qfalse, &tw );
  1119. }
  1120. }
  1121. if ( dump ) {
  1122. PrintOccluded( occluded, sampleWidth, sampleHeight );
  1123. }
  1124. // calculate average values for occluded samples
  1125. for ( i = 0 ; i < sampleWidth ; i++ ) {
  1126. for ( j = 0 ; j < sampleHeight ; j++ ) {
  1127. if ( !occluded[i][j] ) {
  1128. continue;
  1129. }
  1130. // scan all surrounding samples
  1131. count = 0;
  1132. VectorClear( average );
  1133. for ( x = -1 ; x <= 1; x++ ) {
  1134. for ( y = -1 ; y <= 1 ; y++ ) {
  1135. if ( i + x < 0 || i + x >= sampleWidth ) {
  1136. continue;
  1137. }
  1138. if ( j + y < 0 || j + y >= sampleHeight ) {
  1139. continue;
  1140. }
  1141. if ( occluded[i+x][j+y] ) {
  1142. continue;
  1143. }
  1144. count++;
  1145. VectorAdd( color[i+x][j+y], average, average );
  1146. }
  1147. }
  1148. if ( count ) {
  1149. VectorScale( average, 1.0/count, color[i][j] );
  1150. }
  1151. }
  1152. }
  1153. // average together the values if we are extra sampling
  1154. if ( ds->lightmapWidth != sampleWidth ) {
  1155. for ( i = 0 ; i < ds->lightmapWidth ; i++ ) {
  1156. for ( j = 0 ; j < ds->lightmapHeight ; j++ ) {
  1157. for ( k = 0 ; k < 3 ; k++ ) {
  1158. float value, coverage;
  1159. value = color[i*2][j*2][k] + color[i*2][j*2+1][k] +
  1160. color[i*2+1][j*2][k] + color[i*2+1][j*2+1][k];
  1161. coverage = 4;
  1162. if ( extraWide ) {
  1163. // wider than box filter
  1164. if ( i > 0 ) {
  1165. value += color[i*2-1][j*2][k] + color[i*2-1][j*2+1][k];
  1166. value += color[i*2-2][j*2][k] + color[i*2-2][j*2+1][k];
  1167. coverage += 4;
  1168. }
  1169. if ( i < ds->lightmapWidth - 1 ) {
  1170. value += color[i*2+2][j*2][k] + color[i*2+2][j*2+1][k];
  1171. value += color[i*2+3][j*2][k] + color[i*2+3][j*2+1][k];
  1172. coverage += 4;
  1173. }
  1174. if ( j > 0 ) {
  1175. value += color[i*2][j*2-1][k] + color[i*2+1][j*2-1][k];
  1176. value += color[i*2][j*2-2][k] + color[i*2+1][j*2-2][k];
  1177. coverage += 4;
  1178. }
  1179. if ( j < ds->lightmapHeight - 1 ) {
  1180. value += color[i*2][j*2+2][k] + color[i*2+1][j*2+2][k];
  1181. value += color[i*2][j*2+3][k] + color[i*2+1][j*2+3][k];
  1182. coverage += 2;
  1183. }
  1184. }
  1185. color[i][j][k] = value / coverage;
  1186. }
  1187. }
  1188. }
  1189. }
  1190. // optionally create a debugging border around the lightmap
  1191. if ( lightmapBorder ) {
  1192. for ( i = 0 ; i < ds->lightmapWidth ; i++ ) {
  1193. color[i][0][0] = 255;
  1194. color[i][0][1] = 0;
  1195. color[i][0][2] = 0;
  1196. color[i][ds->lightmapHeight-1][0] = 255;
  1197. color[i][ds->lightmapHeight-1][1] = 0;
  1198. color[i][ds->lightmapHeight-1][2] = 0;
  1199. }
  1200. for ( i = 0 ; i < ds->lightmapHeight ; i++ ) {
  1201. color[0][i][0] = 255;
  1202. color[0][i][1] = 0;
  1203. color[0][i][2] = 0;
  1204. color[ds->lightmapWidth-1][i][0] = 255;
  1205. color[ds->lightmapWidth-1][i][1] = 0;
  1206. color[ds->lightmapWidth-1][i][2] = 0;
  1207. }
  1208. }
  1209. // clamp the colors to bytes and store off
  1210. for ( i = 0 ; i < ds->lightmapWidth ; i++ ) {
  1211. for ( j = 0 ; j < ds->lightmapHeight ; j++ ) {
  1212. k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j)
  1213. * LIGHTMAP_WIDTH + ds->lightmapX + i;
  1214. ColorToBytes( color[i][j], lightBytes + k*3 );
  1215. }
  1216. }
  1217. if (ds->surfaceType == MST_PATCH)
  1218. {
  1219. FreeMesh(mesh);
  1220. }
  1221. }
  1222. //=============================================================================
  1223. vec3_t gridMins;
  1224. vec3_t gridSize = { 64, 64, 128 };
  1225. int gridBounds[3];
  1226. /*
  1227. ========================
  1228. LightContributionToPoint
  1229. ========================
  1230. */
  1231. qboolean LightContributionToPoint( const light_t *light, const vec3_t origin,
  1232. vec3_t color, traceWork_t *tw ) {
  1233. trace_t trace;
  1234. float add;
  1235. add = 0;
  1236. VectorClear( color );
  1237. // testing exact PTPFF
  1238. if ( exactPointToPolygon && light->type == emit_area ) {
  1239. float factor;
  1240. float d;
  1241. vec3_t normal;
  1242. // see if the point is behind the light
  1243. d = DotProduct( origin, light->normal ) - light->dist;
  1244. if ( !light->twosided ) {
  1245. if ( d < 1 ) {
  1246. return qfalse; // point is behind light
  1247. }
  1248. }
  1249. // test occlusion
  1250. // clip the line, tracing from the surface towards the light
  1251. TraceLine( origin, light->origin, &trace, qfalse, tw );
  1252. if ( trace.passSolid ) {
  1253. return qfalse;
  1254. }
  1255. // calculate the contribution
  1256. VectorSubtract( light->origin, origin, normal );
  1257. if ( VectorNormalize( normal, normal ) == 0 ) {
  1258. return qfalse;
  1259. }
  1260. factor = PointToPolygonFormFactor( origin, normal, light->w );
  1261. if ( factor <= 0 ) {
  1262. if ( light->twosided ) {
  1263. factor = -factor;
  1264. } else {
  1265. return qfalse;
  1266. }
  1267. }
  1268. VectorScale( light->emitColor, factor, color );
  1269. return qtrue;
  1270. }
  1271. // calculate the amount of light at this sample
  1272. if ( light->type == emit_point || light->type == emit_spotlight ) {
  1273. vec3_t dir;
  1274. float dist;
  1275. VectorSubtract( light->origin, origin, dir );
  1276. dist = VectorLength( dir );
  1277. // clamp the distance to prevent super hot spots
  1278. if ( dist < 16 ) {
  1279. dist = 16;
  1280. }
  1281. if ( light->linearLight ) {
  1282. add = light->photons * linearScale - dist;
  1283. if ( add < 0 ) {
  1284. add = 0;
  1285. }
  1286. } else {
  1287. add = light->photons / ( dist * dist );
  1288. }
  1289. } else {
  1290. return qfalse;
  1291. }
  1292. if ( add <= 1.0 ) {
  1293. return qfalse;
  1294. }
  1295. // clip the line, tracing from the surface towards the light
  1296. TraceLine( origin, light->origin, &trace, qfalse, tw );
  1297. // other light rays must not hit anything
  1298. if ( trace.passSolid ) {
  1299. return qfalse;
  1300. }
  1301. // add the result
  1302. color[0] = add * light->color[0];
  1303. color[1] = add * light->color[1];
  1304. color[2] = add * light->color[2];
  1305. return qtrue;
  1306. }
  1307. typedef struct {
  1308. vec3_t dir;
  1309. vec3_t color;
  1310. } contribution_t;
  1311. /*
  1312. =============
  1313. TraceGrid
  1314. Grid samples are foe quickly determining the lighting
  1315. of dynamically placed entities in the world
  1316. =============
  1317. */
  1318. #define MAX_CONTRIBUTIONS 1024
  1319. void TraceGrid( int num ) {
  1320. int x, y, z;
  1321. vec3_t origin;
  1322. light_t *light;
  1323. vec3_t color;
  1324. int mod;
  1325. vec3_t directedColor;
  1326. vec3_t summedDir;
  1327. contribution_t contributions[MAX_CONTRIBUTIONS];
  1328. int numCon;
  1329. int i;
  1330. traceWork_t tw;
  1331. float addSize;
  1332. mod = num;
  1333. z = mod / ( gridBounds[0] * gridBounds[1] );
  1334. mod -= z * ( gridBounds[0] * gridBounds[1] );
  1335. y = mod / gridBounds[0];
  1336. mod -= y * gridBounds[0];
  1337. x = mod;
  1338. origin[0] = gridMins[0] + x * gridSize[0];
  1339. origin[1] = gridMins[1] + y * gridSize[1];
  1340. origin[2] = gridMins[2] + z * gridSize[2];
  1341. if ( PointInSolid( origin ) ) {
  1342. vec3_t baseOrigin;
  1343. int step;
  1344. VectorCopy( origin, baseOrigin );
  1345. // try to nudge the origin around to find a valid point
  1346. for ( step = 9 ; step <= 18 ; step += 9 ) {
  1347. for ( i = 0 ; i < 8 ; i++ ) {
  1348. VectorCopy( baseOrigin, origin );
  1349. if ( i & 1 ) {
  1350. origin[0] += step;
  1351. } else {
  1352. origin[0] -= step;
  1353. }
  1354. if ( i & 2 ) {
  1355. origin[1] += step;
  1356. } else {
  1357. origin[1] -= step;
  1358. }
  1359. if ( i & 4 ) {
  1360. origin[2] += step;
  1361. } else {
  1362. origin[2] -= step;
  1363. }
  1364. if ( !PointInSolid( origin ) ) {
  1365. break;
  1366. }
  1367. }
  1368. if ( i != 8 ) {
  1369. break;
  1370. }
  1371. }
  1372. if ( step > 18 ) {
  1373. // can't find a valid point at all
  1374. for ( i = 0 ; i < 8 ; i++ ) {
  1375. gridData[ num*8 + i ] = 0;
  1376. }
  1377. return;
  1378. }
  1379. }
  1380. VectorClear( summedDir );
  1381. // trace to all the lights
  1382. // find the major light direction, and divide the
  1383. // total light between that along the direction and
  1384. // the remaining in the ambient
  1385. numCon = 0;
  1386. for ( light = lights ; light ; light = light->next ) {
  1387. vec3_t add;
  1388. vec3_t dir;
  1389. float addSize;
  1390. if ( !LightContributionToPoint( light, origin, add, &tw ) ) {
  1391. continue;
  1392. }
  1393. VectorSubtract( light->origin, origin, dir );
  1394. VectorNormalize( dir, dir );
  1395. VectorCopy( add, contributions[numCon].color );
  1396. VectorCopy( dir, contributions[numCon].dir );
  1397. numCon++;
  1398. addSize = VectorLength( add );
  1399. VectorMA( summedDir, addSize, dir, summedDir );
  1400. if ( numCon == MAX_CONTRIBUTIONS-1 ) {
  1401. break;
  1402. }
  1403. }
  1404. //
  1405. // trace directly to the sun
  1406. //
  1407. SunToPoint( origin, &tw, color );
  1408. addSize = VectorLength( color );
  1409. if ( addSize > 0 ) {
  1410. VectorCopy( color, contributions[numCon].color );
  1411. VectorCopy( sunDirection, contributions[numCon].dir );
  1412. VectorMA( summedDir, addSize, sunDirection, summedDir );
  1413. numCon++;
  1414. }
  1415. // now that we have identified the primary light direction,
  1416. // go back and seperate all the light into directed and ambient
  1417. VectorNormalize( summedDir, summedDir );
  1418. VectorCopy( ambientColor, color );
  1419. VectorClear( directedColor );
  1420. for ( i = 0 ; i < numCon ; i++ ) {
  1421. float d;
  1422. d = DotProduct( contributions[i].dir, summedDir );
  1423. if ( d < 0 ) {
  1424. d = 0;
  1425. }
  1426. VectorMA( directedColor, d, contributions[i].color, directedColor );
  1427. // the ambient light will be at 1/4 the value of directed light
  1428. d = 0.25 * ( 1.0 - d );
  1429. VectorMA( color, d, contributions[i].color, color );
  1430. }
  1431. // now do some fudging to keep the ambient from being too low
  1432. VectorMA( color, 0.25, directedColor, color );
  1433. //
  1434. // save the resulting value out
  1435. //
  1436. ColorToBytes( color, gridData + num*8 );
  1437. ColorToBytes( directedColor, gridData + num*8 + 3 );
  1438. VectorNormalize( summedDir, summedDir );
  1439. NormalToLatLong( summedDir, gridData + num*8 + 6);
  1440. }
  1441. /*
  1442. =============
  1443. SetupGrid
  1444. =============
  1445. */
  1446. void SetupGrid( void ) {
  1447. int i;
  1448. vec3_t maxs;
  1449. for ( i = 0 ; i < 3 ; i++ ) {
  1450. gridMins[i] = gridSize[i] * ceil( dmodels[0].mins[i] / gridSize[i] );
  1451. maxs[i] = gridSize[i] * floor( dmodels[0].maxs[i] / gridSize[i] );
  1452. gridBounds[i] = (maxs[i] - gridMins[i])/gridSize[i] + 1;
  1453. }
  1454. numGridPoints = gridBounds[0] * gridBounds[1] * gridBounds[2];
  1455. if (numGridPoints * 8 >= MAX_MAP_LIGHTGRID)
  1456. Error("MAX_MAP_LIGHTGRID");
  1457. qprintf( "%5i gridPoints\n", numGridPoints );
  1458. }
  1459. //=============================================================================
  1460. /*
  1461. =============
  1462. RemoveLightsInSolid
  1463. =============
  1464. */
  1465. void RemoveLightsInSolid(void)
  1466. {
  1467. light_t *light, *prev;
  1468. int numsolid = 0;
  1469. prev = NULL;
  1470. for ( light = lights ; light ; ) {
  1471. if (PointInSolid(light->origin))
  1472. {
  1473. if (prev) prev->next = light->next;
  1474. else lights = light->next;
  1475. if (light->w)
  1476. FreeWinding(light->w);
  1477. free(light);
  1478. numsolid++;
  1479. if (prev)
  1480. light = prev->next;
  1481. else
  1482. light = lights;
  1483. }
  1484. else
  1485. {
  1486. prev = light;
  1487. light = light->next;
  1488. }
  1489. }
  1490. _printf (" %7i lights in solid\n", numsolid);
  1491. }
  1492. /*
  1493. =============
  1494. LightWorld
  1495. =============
  1496. */
  1497. void LightWorld (void) {
  1498. float f;
  1499. // determine the number of grid points
  1500. SetupGrid();
  1501. // find the optional world ambient
  1502. GetVectorForKey( &entities[0], "_color", ambientColor );
  1503. f = FloatForKey( &entities[0], "ambient" );
  1504. VectorScale( ambientColor, f, ambientColor );
  1505. // create lights out of patches and lights
  1506. qprintf ("--- CreateLights ---\n");
  1507. CreateEntityLights ();
  1508. qprintf ("%i point lights\n", numPointLights);
  1509. qprintf ("%i area lights\n", numAreaLights);
  1510. if (!nogridlighting) {
  1511. qprintf ("--- TraceGrid ---\n");
  1512. RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid );
  1513. qprintf( "%i x %i x %i = %i grid\n", gridBounds[0], gridBounds[1],
  1514. gridBounds[2], numGridPoints);
  1515. }
  1516. qprintf ("--- TraceLtm ---\n");
  1517. RunThreadsOnIndividual( numDrawSurfaces, qtrue, TraceLtm );
  1518. qprintf( "%5i visible samples\n", c_visible );
  1519. qprintf( "%5i occluded samples\n", c_occluded );
  1520. }
  1521. /*
  1522. ========
  1523. CreateFilters
  1524. EXPERIMENTAL, UNUSED
  1525. Look for transparent light filter surfaces.
  1526. This will only work for flat 3*3 patches that exactly hold one copy of the texture.
  1527. ========
  1528. */
  1529. #define PLANAR_PATCH_EPSILON 0.1
  1530. void CreateFilters( void ) {
  1531. int i;
  1532. filter_t *f;
  1533. dsurface_t *ds;
  1534. shaderInfo_t *si;
  1535. drawVert_t *v1, *v2, *v3;
  1536. vec3_t d1, d2;
  1537. int vertNum;
  1538. numFilters = 0;
  1539. return;
  1540. for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
  1541. ds = &drawSurfaces[i];
  1542. if ( !ds->patchWidth ) {
  1543. continue;
  1544. }
  1545. si = ShaderInfoForShader( dshaders[ ds->shaderNum ].shader );
  1546. /*
  1547. if ( !(si->surfaceFlags & SURF_LIGHTFILTER) ) {
  1548. continue;
  1549. }
  1550. */
  1551. // we have a filter patch
  1552. v1 = &drawVerts[ ds->firstVert ];
  1553. if ( ds->patchWidth != 3 || ds->patchHeight != 3 ) {
  1554. _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't a 3 by 3\n",
  1555. v1->xyz[0], v1->xyz[1], v1->xyz[2] );
  1556. continue;
  1557. }
  1558. if ( numFilters == MAX_FILTERS ) {
  1559. Error( "MAX_FILTERS" );
  1560. }
  1561. f = &filters[ numFilters ];
  1562. numFilters++;
  1563. v2 = &drawVerts[ ds->firstVert + 2 ];
  1564. v3 = &drawVerts[ ds->firstVert + 6 ];
  1565. VectorSubtract( v2->xyz, v1->xyz, d1 );
  1566. VectorSubtract( v3->xyz, v1->xyz, d2 );
  1567. VectorNormalize( d1, d1 );
  1568. VectorNormalize( d2, d2 );
  1569. CrossProduct( d1, d2, f->plane );
  1570. f->plane[3] = DotProduct( v1->xyz, f->plane );
  1571. // make sure all the control points are on the plane
  1572. for ( vertNum = 0 ; vertNum < ds->numVerts ; vertNum++ ) {
  1573. float d;
  1574. d = DotProduct( drawVerts[ ds->firstVert + vertNum ].xyz, f->plane ) - f->plane[3];
  1575. if ( fabs( d ) > PLANAR_PATCH_EPSILON ) {
  1576. break;
  1577. }
  1578. }
  1579. if ( vertNum != ds->numVerts ) {
  1580. numFilters--;
  1581. _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't flat\n",
  1582. v1->xyz[0], v1->xyz[1], v1->xyz[2] );
  1583. continue;
  1584. }
  1585. }
  1586. f = &filters[0];
  1587. numFilters = 1;
  1588. f->plane[0] = 1;
  1589. f->plane[1] = 0;
  1590. f->plane[2] = 0;
  1591. f->plane[3] = 448;
  1592. f->origin[0] = 448;
  1593. f->origin[1] = 192;
  1594. f->origin[2] = 0;
  1595. f->vectors[0][0] = 0;
  1596. f->vectors[0][1] = -1.0 / 128;
  1597. f->vectors[0][2] = 0;
  1598. f->vectors[1][0] = 0;
  1599. f->vectors[1][1] = 0;
  1600. f->vectors[1][2] = 1.0 / 128;
  1601. f->si = ShaderInfoForShader( "textures/hell/blocks11ct" );
  1602. }
  1603. /*
  1604. =============
  1605. VertexLightingThread
  1606. =============
  1607. */
  1608. void VertexLightingThread(int num) {
  1609. dsurface_t *ds;
  1610. traceWork_t tw;
  1611. shaderInfo_t *si;
  1612. ds = &drawSurfaces[num];
  1613. // vertex-lit triangle model
  1614. if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
  1615. return;
  1616. }
  1617. if (novertexlighting)
  1618. return;
  1619. if ( ds->lightmapNum == -1 ) {
  1620. return; // doesn't need lighting at all
  1621. }
  1622. si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
  1623. // calculate the vertex lighting for gouraud shade mode
  1624. VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw );
  1625. }
  1626. /*
  1627. =============
  1628. TriSoupLightingThread
  1629. =============
  1630. */
  1631. void TriSoupLightingThread(int num) {
  1632. dsurface_t *ds;
  1633. traceWork_t tw;
  1634. shaderInfo_t *si;
  1635. ds = &drawSurfaces[num];
  1636. si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
  1637. // vertex-lit triangle model
  1638. if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
  1639. VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw );
  1640. }
  1641. }
  1642. /*
  1643. =============
  1644. GridAndVertexLighting
  1645. =============
  1646. */
  1647. void GridAndVertexLighting(void) {
  1648. SetupGrid();
  1649. FindSkyBrushes();
  1650. CreateFilters();
  1651. InitTrace();
  1652. CreateEntityLights ();
  1653. CreateSurfaceLights();
  1654. if (!nogridlighting) {
  1655. _printf ("--- TraceGrid ---\n");
  1656. RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid );
  1657. }
  1658. if (!novertexlighting) {
  1659. _printf ("--- Vertex Lighting ---\n");
  1660. RunThreadsOnIndividual( numDrawSurfaces, qtrue, VertexLightingThread );
  1661. }
  1662. _printf("--- Model Lighting ---\n");
  1663. RunThreadsOnIndividual( numDrawSurfaces, qtrue, TriSoupLightingThread );
  1664. }
  1665. /*
  1666. ========
  1667. LightMain
  1668. ========
  1669. */
  1670. int LightMain (int argc, char **argv) {
  1671. int i;
  1672. double start, end;
  1673. const char *value;
  1674. _printf ("----- Lighting ----\n");
  1675. verbose = qfalse;
  1676. for (i=1 ; i<argc ; i++) {
  1677. if (!strcmp(argv[i],"-tempname"))
  1678. {
  1679. i++;
  1680. } else if (!strcmp(argv[i],"-v")) {
  1681. verbose = qtrue;
  1682. } else if (!strcmp(argv[i],"-threads")) {
  1683. numthreads = atoi (argv[i+1]);
  1684. i++;
  1685. } else if (!strcmp(argv[i],"-area")) {
  1686. areaScale *= atof(argv[i+1]);
  1687. _printf ("area light scaling at %f\n", areaScale);
  1688. i++;
  1689. } else if (!strcmp(argv[i],"-point")) {
  1690. pointScale *= atof(argv[i+1]);
  1691. _printf ("point light scaling at %f\n", pointScale);
  1692. i++;
  1693. } else if (!strcmp(argv[i],"-notrace")) {
  1694. notrace = qtrue;
  1695. _printf ("No occlusion tracing\n");
  1696. } else if (!strcmp(argv[i],"-patchshadows")) {
  1697. patchshadows = qtrue;
  1698. _printf ("Patch shadow casting enabled\n");
  1699. } else if (!strcmp(argv[i],"-extra")) {
  1700. extra = qtrue;
  1701. _printf ("Extra detail tracing\n");
  1702. } else if (!strcmp(argv[i],"-extrawide")) {
  1703. extra = qtrue;
  1704. extraWide = qtrue;
  1705. _printf ("Extra wide detail tracing\n");
  1706. } else if (!strcmp(argv[i], "-samplesize")) {
  1707. samplesize = atoi(argv[i+1]);
  1708. if (samplesize < 1) samplesize = 1;
  1709. i++;
  1710. _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize);
  1711. } else if (!strcmp(argv[i], "-novertex")) {
  1712. novertexlighting = qtrue;
  1713. _printf("no vertex lighting = true\n");
  1714. } else if (!strcmp(argv[i], "-nogrid")) {
  1715. nogridlighting = qtrue;
  1716. _printf("no grid lighting = true\n");
  1717. } else if (!strcmp(argv[i],"-border")) {
  1718. lightmapBorder = qtrue;
  1719. _printf ("Adding debug border to lightmaps\n");
  1720. } else if (!strcmp(argv[i],"-nosurf")) {
  1721. noSurfaces = qtrue;
  1722. _printf ("Not tracing against surfaces\n" );
  1723. } else if (!strcmp(argv[i],"-dump")) {
  1724. dump = qtrue;
  1725. _printf ("Dumping occlusion maps\n");
  1726. } else {
  1727. break;
  1728. }
  1729. }
  1730. ThreadSetDefault ();
  1731. if (i != argc - 1) {
  1732. _printf("usage: q3map -light [-<switch> [-<switch> ...]] <mapname>\n"
  1733. "\n"
  1734. "Switches:\n"
  1735. " v = verbose output\n"
  1736. " threads <X> = set number of threads to X\n"
  1737. " area <V> = set the area light scale to V\n"
  1738. " point <W> = set the point light scale to W\n"
  1739. " notrace = don't cast any shadows\n"
  1740. " extra = enable super sampling for anti-aliasing\n"
  1741. " extrawide = same as extra but smoothen more\n"
  1742. " nogrid = don't calculate light grid for dynamic model lighting\n"
  1743. " novertex = don't calculate vertex lighting\n"
  1744. " samplesize <N> = set the lightmap pixel size to NxN units\n");
  1745. exit(0);
  1746. }
  1747. start = I_FloatTime ();
  1748. SetQdirFromPath (argv[i]);
  1749. #ifdef _WIN32
  1750. InitPakFile(gamedir, NULL);
  1751. #endif
  1752. strcpy (source, ExpandArg(argv[i]));
  1753. StripExtension (source);
  1754. DefaultExtension (source, ".bsp");
  1755. LoadShaderInfo();
  1756. _printf ("reading %s\n", source);
  1757. LoadBSPFile (source);
  1758. FindSkyBrushes();
  1759. ParseEntities();
  1760. value = ValueForKey( &entities[0], "gridsize" );
  1761. if (strlen(value)) {
  1762. sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] );
  1763. _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]);
  1764. }
  1765. CreateFilters();
  1766. InitTrace();
  1767. SetEntityOrigins();
  1768. CountLightmaps();
  1769. CreateSurfaceLights();
  1770. LightWorld();
  1771. _printf ("writing %s\n", source);
  1772. WriteBSPFile (source);
  1773. end = I_FloatTime ();
  1774. _printf ("%5.0f seconds elapsed\n", end-start);
  1775. return 0;
  1776. }