PageRenderTime 51ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/tools/quake3/q3map2/light.c

https://gitlab.com/illwieckz/netradiant
C | 3039 lines | 2088 code | 493 blank | 458 comment | 638 complexity | 38f61902dbf0ca3b9a61ba69e4cbfb93 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /* -------------------------------------------------------------------------------
  2. Copyright (C) 1999-2007 id Software, Inc. and contributors.
  3. For a list of contributors, see the accompanying CONTRIBUTORS file.
  4. This file is part of GtkRadiant.
  5. GtkRadiant is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. GtkRadiant is distributed in the hope that it will be useful,
  10. 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 GtkRadiant; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ----------------------------------------------------------------------------------
  17. This code has been altered significantly from its original form, to support
  18. several games based on the Quake III Arena engine, in the form of "Q3Map2."
  19. ------------------------------------------------------------------------------- */
  20. /* marker */
  21. #define LIGHT_C
  22. /* dependencies */
  23. #include "q3map2.h"
  24. /*
  25. CreateSunLight() - ydnar
  26. this creates a sun light
  27. */
  28. static void CreateSunLight( sun_t *sun ){
  29. int i;
  30. float photons, d, angle, elevation, da, de;
  31. vec3_t direction;
  32. light_t *light;
  33. /* dummy check */
  34. if ( sun == NULL ) {
  35. return;
  36. }
  37. /* fixup */
  38. if ( sun->numSamples < 1 ) {
  39. sun->numSamples = 1;
  40. }
  41. /* set photons */
  42. photons = sun->photons / sun->numSamples;
  43. /* create the right number of suns */
  44. for ( i = 0; i < sun->numSamples; i++ )
  45. {
  46. /* calculate sun direction */
  47. if ( i == 0 ) {
  48. VectorCopy( sun->direction, direction );
  49. }
  50. else
  51. {
  52. /*
  53. sun->direction[ 0 ] = cos( angle ) * cos( elevation );
  54. sun->direction[ 1 ] = sin( angle ) * cos( elevation );
  55. sun->direction[ 2 ] = sin( elevation );
  56. xz_dist = sqrt( x*x + z*z )
  57. latitude = atan2( xz_dist, y ) * RADIANS
  58. longitude = atan2( x, z ) * RADIANS
  59. */
  60. d = sqrt( sun->direction[ 0 ] * sun->direction[ 0 ] + sun->direction[ 1 ] * sun->direction[ 1 ] );
  61. angle = atan2( sun->direction[ 1 ], sun->direction[ 0 ] );
  62. elevation = atan2( sun->direction[ 2 ], d );
  63. /* jitter the angles (loop to keep random sample within sun->deviance steridians) */
  64. do
  65. {
  66. da = ( Random() * 2.0f - 1.0f ) * sun->deviance;
  67. de = ( Random() * 2.0f - 1.0f ) * sun->deviance;
  68. }
  69. while ( ( da * da + de * de ) > ( sun->deviance * sun->deviance ) );
  70. angle += da;
  71. elevation += de;
  72. /* debug code */
  73. //% Sys_Printf( "%d: Angle: %3.4f Elevation: %3.3f\n", sun->numSamples, (angle / Q_PI * 180.0f), (elevation / Q_PI * 180.0f) );
  74. /* create new vector */
  75. direction[ 0 ] = cos( angle ) * cos( elevation );
  76. direction[ 1 ] = sin( angle ) * cos( elevation );
  77. direction[ 2 ] = sin( elevation );
  78. }
  79. /* create a light */
  80. numSunLights++;
  81. light = safe_malloc( sizeof( *light ) );
  82. memset( light, 0, sizeof( *light ) );
  83. light->next = lights;
  84. lights = light;
  85. /* initialize the light */
  86. light->flags = LIGHT_SUN_DEFAULT;
  87. light->type = EMIT_SUN;
  88. light->fade = 1.0f;
  89. light->falloffTolerance = falloffTolerance;
  90. light->filterRadius = sun->filterRadius / sun->numSamples;
  91. light->style = noStyles ? LS_NORMAL : sun->style;
  92. /* set the light's position out to infinity */
  93. VectorMA( vec3_origin, ( MAX_WORLD_COORD * 8.0f ), direction, light->origin ); /* MAX_WORLD_COORD * 2.0f */
  94. /* set the facing to be the inverse of the sun direction */
  95. VectorScale( direction, -1.0, light->normal );
  96. light->dist = DotProduct( light->origin, light->normal );
  97. /* set color and photons */
  98. VectorCopy( sun->color, light->color );
  99. light->photons = photons * skyScale;
  100. }
  101. /* another sun? */
  102. if ( sun->next != NULL ) {
  103. CreateSunLight( sun->next );
  104. }
  105. }
  106. /*
  107. CreateSkyLights() - ydnar
  108. simulates sky light with multiple suns
  109. */
  110. static void CreateSkyLights( vec3_t color, float value, int iterations, float filterRadius, int style ){
  111. int i, j, numSuns;
  112. int angleSteps, elevationSteps;
  113. float angle, elevation;
  114. float angleStep, elevationStep;
  115. sun_t sun;
  116. /* dummy check */
  117. if ( value <= 0.0f || iterations < 2 ) {
  118. return;
  119. }
  120. /* basic sun setup */
  121. VectorCopy( color, sun.color );
  122. sun.deviance = 0.0f;
  123. sun.filterRadius = filterRadius;
  124. sun.numSamples = 1;
  125. sun.style = noStyles ? LS_NORMAL : style;
  126. sun.next = NULL;
  127. /* setup */
  128. elevationSteps = iterations - 1;
  129. angleSteps = elevationSteps * 4;
  130. angle = 0.0f;
  131. elevationStep = DEG2RAD( 90.0f / iterations ); /* skip elevation 0 */
  132. angleStep = DEG2RAD( 360.0f / angleSteps );
  133. /* calc individual sun brightness */
  134. numSuns = angleSteps * elevationSteps + 1;
  135. sun.photons = value / numSuns;
  136. /* iterate elevation */
  137. elevation = elevationStep * 0.5f;
  138. angle = 0.0f;
  139. for ( i = 0, elevation = elevationStep * 0.5f; i < elevationSteps; i++ )
  140. {
  141. /* iterate angle */
  142. for ( j = 0; j < angleSteps; j++ )
  143. {
  144. /* create sun */
  145. sun.direction[ 0 ] = cos( angle ) * cos( elevation );
  146. sun.direction[ 1 ] = sin( angle ) * cos( elevation );
  147. sun.direction[ 2 ] = sin( elevation );
  148. CreateSunLight( &sun );
  149. /* move */
  150. angle += angleStep;
  151. }
  152. /* move */
  153. elevation += elevationStep;
  154. angle += angleStep / elevationSteps;
  155. }
  156. /* create vertical sun */
  157. VectorSet( sun.direction, 0.0f, 0.0f, 1.0f );
  158. CreateSunLight( &sun );
  159. /* short circuit */
  160. return;
  161. }
  162. /*
  163. CreateEntityLights()
  164. creates lights from light entities
  165. */
  166. void CreateEntityLights( void ){
  167. int i, j;
  168. light_t *light, *light2;
  169. entity_t *e, *e2;
  170. const char *name;
  171. const char *target;
  172. vec3_t dest;
  173. const char *_color;
  174. float intensity, scale, deviance, filterRadius;
  175. int spawnflags, flags, numSamples;
  176. qboolean junior;
  177. /* go throught entity list and find lights */
  178. for ( i = 0; i < numEntities; i++ )
  179. {
  180. /* get entity */
  181. e = &entities[ i ];
  182. name = ValueForKey( e, "classname" );
  183. /* ydnar: check for lightJunior */
  184. if ( Q_strncasecmp( name, "lightJunior", 11 ) == 0 ) {
  185. junior = qtrue;
  186. }
  187. else if ( Q_strncasecmp( name, "light", 5 ) == 0 ) {
  188. junior = qfalse;
  189. }
  190. else{
  191. continue;
  192. }
  193. /* lights with target names (and therefore styles) are only parsed from BSP */
  194. target = ValueForKey( e, "targetname" );
  195. if ( target[ 0 ] != '\0' && i >= numBSPEntities ) {
  196. continue;
  197. }
  198. /* create a light */
  199. numPointLights++;
  200. light = safe_malloc( sizeof( *light ) );
  201. memset( light, 0, sizeof( *light ) );
  202. light->next = lights;
  203. lights = light;
  204. /* handle spawnflags */
  205. spawnflags = IntForKey( e, "spawnflags" );
  206. /* ydnar: quake 3+ light behavior */
  207. if ( wolfLight == qfalse ) {
  208. /* set default flags */
  209. flags = LIGHT_Q3A_DEFAULT;
  210. /* linear attenuation? */
  211. if ( spawnflags & 1 ) {
  212. flags |= LIGHT_ATTEN_LINEAR;
  213. flags &= ~LIGHT_ATTEN_ANGLE;
  214. }
  215. /* no angle attenuate? */
  216. if ( spawnflags & 2 ) {
  217. flags &= ~LIGHT_ATTEN_ANGLE;
  218. }
  219. }
  220. /* ydnar: wolf light behavior */
  221. else
  222. {
  223. /* set default flags */
  224. flags = LIGHT_WOLF_DEFAULT;
  225. /* inverse distance squared attenuation? */
  226. if ( spawnflags & 1 ) {
  227. flags &= ~LIGHT_ATTEN_LINEAR;
  228. flags |= LIGHT_ATTEN_ANGLE;
  229. }
  230. /* angle attenuate? */
  231. if ( spawnflags & 2 ) {
  232. flags |= LIGHT_ATTEN_ANGLE;
  233. }
  234. }
  235. /* other flags (borrowed from wolf) */
  236. /* wolf dark light? */
  237. if ( ( spawnflags & 4 ) || ( spawnflags & 8 ) ) {
  238. flags |= LIGHT_DARK;
  239. }
  240. /* nogrid? */
  241. if ( spawnflags & 16 ) {
  242. flags &= ~LIGHT_GRID;
  243. }
  244. /* junior? */
  245. if ( junior ) {
  246. flags |= LIGHT_GRID;
  247. flags &= ~LIGHT_SURFACES;
  248. }
  249. /* vortex: unnormalized? */
  250. if ( spawnflags & 32 ) {
  251. flags |= LIGHT_UNNORMALIZED;
  252. }
  253. /* vortex: distance atten? */
  254. if ( spawnflags & 64 ) {
  255. flags |= LIGHT_ATTEN_DISTANCE;
  256. }
  257. /* store the flags */
  258. light->flags = flags;
  259. /* ydnar: set fade key (from wolf) */
  260. light->fade = 1.0f;
  261. if ( light->flags & LIGHT_ATTEN_LINEAR ) {
  262. light->fade = FloatForKey( e, "fade" );
  263. if ( light->fade == 0.0f ) {
  264. light->fade = 1.0f;
  265. }
  266. }
  267. /* ydnar: set angle scaling (from vlight) */
  268. light->angleScale = FloatForKey( e, "_anglescale" );
  269. if ( light->angleScale != 0.0f ) {
  270. light->flags |= LIGHT_ATTEN_ANGLE;
  271. }
  272. /* set origin */
  273. GetVectorForKey( e, "origin", light->origin );
  274. light->style = IntForKey( e, "_style" );
  275. if ( light->style == LS_NORMAL ) {
  276. light->style = IntForKey( e, "style" );
  277. }
  278. if ( light->style < LS_NORMAL || light->style >= LS_NONE ) {
  279. Error( "Invalid lightstyle (%d) on entity %d", light->style, i );
  280. }
  281. if ( light->style != LS_NORMAL ) {
  282. Sys_FPrintf( SYS_WRN, "WARNING: Styled light found targeting %s\n **", target );
  283. }
  284. /* set light intensity */
  285. intensity = FloatForKey( e, "_light" );
  286. if ( intensity == 0.0f ) {
  287. intensity = FloatForKey( e, "light" );
  288. }
  289. if ( intensity == 0.0f ) {
  290. intensity = 300.0f;
  291. }
  292. /* ydnar: set light scale (sof2) */
  293. scale = FloatForKey( e, "scale" );
  294. if ( scale == 0.0f ) {
  295. scale = 1.0f;
  296. }
  297. intensity *= scale;
  298. /* ydnar: get deviance and samples */
  299. deviance = FloatForKey( e, "_deviance" );
  300. if ( deviance == 0.0f ) {
  301. deviance = FloatForKey( e, "_deviation" );
  302. }
  303. if ( deviance == 0.0f ) {
  304. deviance = FloatForKey( e, "_jitter" );
  305. }
  306. numSamples = IntForKey( e, "_samples" );
  307. if ( deviance < 0.0f || numSamples < 1 ) {
  308. deviance = 0.0f;
  309. numSamples = 1;
  310. }
  311. intensity /= numSamples;
  312. /* ydnar: get filter radius */
  313. filterRadius = FloatForKey( e, "_filterradius" );
  314. if ( filterRadius == 0.0f ) {
  315. filterRadius = FloatForKey( e, "_filteradius" );
  316. }
  317. if ( filterRadius == 0.0f ) {
  318. filterRadius = FloatForKey( e, "_filter" );
  319. }
  320. if ( filterRadius < 0.0f ) {
  321. filterRadius = 0.0f;
  322. }
  323. light->filterRadius = filterRadius;
  324. /* set light color */
  325. _color = ValueForKey( e, "_color" );
  326. if ( _color && _color[ 0 ] ) {
  327. sscanf( _color, "%f %f %f", &light->color[ 0 ], &light->color[ 1 ], &light->color[ 2 ] );
  328. if ( colorsRGB ) {
  329. light->color[0] = Image_LinearFloatFromsRGBFloat( light->color[0] );
  330. light->color[1] = Image_LinearFloatFromsRGBFloat( light->color[1] );
  331. light->color[2] = Image_LinearFloatFromsRGBFloat( light->color[2] );
  332. }
  333. if ( !( light->flags & LIGHT_UNNORMALIZED ) ) {
  334. ColorNormalize( light->color, light->color );
  335. }
  336. }
  337. else{
  338. light->color[ 0 ] = light->color[ 1 ] = light->color[ 2 ] = 1.0f;
  339. }
  340. light->extraDist = FloatForKey( e, "_extradist" );
  341. if ( light->extraDist == 0.0f ) {
  342. light->extraDist = extraDist;
  343. }
  344. light->photons = intensity;
  345. light->type = EMIT_POINT;
  346. /* set falloff threshold */
  347. light->falloffTolerance = falloffTolerance / numSamples;
  348. /* lights with a target will be spotlights */
  349. target = ValueForKey( e, "target" );
  350. if ( target[ 0 ] ) {
  351. float radius;
  352. float dist;
  353. sun_t sun;
  354. const char *_sun;
  355. /* get target */
  356. e2 = FindTargetEntity( target );
  357. if ( e2 == NULL ) {
  358. Sys_FPrintf( SYS_WRN, "WARNING: light at (%i %i %i) has missing target\n",
  359. (int) light->origin[ 0 ], (int) light->origin[ 1 ], (int) light->origin[ 2 ] );
  360. light->photons *= pointScale;
  361. }
  362. else
  363. {
  364. /* not a point light */
  365. numPointLights--;
  366. numSpotLights++;
  367. /* make a spotlight */
  368. GetVectorForKey( e2, "origin", dest );
  369. VectorSubtract( dest, light->origin, light->normal );
  370. dist = VectorNormalize( light->normal, light->normal );
  371. radius = FloatForKey( e, "radius" );
  372. if ( !radius ) {
  373. radius = 64;
  374. }
  375. if ( !dist ) {
  376. dist = 64;
  377. }
  378. light->radiusByDist = ( radius + 16 ) / dist;
  379. light->type = EMIT_SPOT;
  380. /* ydnar: wolf mods: spotlights always use nonlinear + angle attenuation */
  381. light->flags &= ~LIGHT_ATTEN_LINEAR;
  382. light->flags |= LIGHT_ATTEN_ANGLE;
  383. light->fade = 1.0f;
  384. /* ydnar: is this a sun? */
  385. _sun = ValueForKey( e, "_sun" );
  386. if ( _sun[ 0 ] == '1' ) {
  387. /* not a spot light */
  388. numSpotLights--;
  389. /* unlink this light */
  390. lights = light->next;
  391. /* make a sun */
  392. VectorScale( light->normal, -1.0f, sun.direction );
  393. VectorCopy( light->color, sun.color );
  394. sun.photons = intensity;
  395. sun.deviance = deviance / 180.0f * Q_PI;
  396. sun.numSamples = numSamples;
  397. sun.style = noStyles ? LS_NORMAL : light->style;
  398. sun.next = NULL;
  399. /* make a sun light */
  400. CreateSunLight( &sun );
  401. /* free original light */
  402. free( light );
  403. light = NULL;
  404. /* skip the rest of this love story */
  405. continue;
  406. }
  407. else
  408. {
  409. light->photons *= spotScale;
  410. }
  411. }
  412. }
  413. else{
  414. light->photons *= pointScale;
  415. }
  416. /* jitter the light */
  417. for ( j = 1; j < numSamples; j++ )
  418. {
  419. /* create a light */
  420. light2 = safe_malloc( sizeof( *light ) );
  421. memcpy( light2, light, sizeof( *light ) );
  422. light2->next = lights;
  423. lights = light2;
  424. /* add to counts */
  425. if ( light->type == EMIT_SPOT ) {
  426. numSpotLights++;
  427. }
  428. else{
  429. numPointLights++;
  430. }
  431. /* jitter it */
  432. light2->origin[ 0 ] = light->origin[ 0 ] + ( Random() * 2.0f - 1.0f ) * deviance;
  433. light2->origin[ 1 ] = light->origin[ 1 ] + ( Random() * 2.0f - 1.0f ) * deviance;
  434. light2->origin[ 2 ] = light->origin[ 2 ] + ( Random() * 2.0f - 1.0f ) * deviance;
  435. }
  436. }
  437. }
  438. /*
  439. CreateSurfaceLights() - ydnar
  440. this hijacks the radiosity code to generate surface lights for first pass
  441. */
  442. #define APPROX_BOUNCE 1.0f
  443. void CreateSurfaceLights( void ){
  444. int i;
  445. bspDrawSurface_t *ds;
  446. surfaceInfo_t *info;
  447. shaderInfo_t *si;
  448. light_t *light;
  449. float subdivide;
  450. vec3_t origin;
  451. clipWork_t cw;
  452. const char *nss;
  453. /* get sun shader supressor */
  454. nss = ValueForKey( &entities[ 0 ], "_noshadersun" );
  455. /* walk the list of surfaces */
  456. for ( i = 0; i < numBSPDrawSurfaces; i++ )
  457. {
  458. /* get surface and other bits */
  459. ds = &bspDrawSurfaces[ i ];
  460. info = &surfaceInfos[ i ];
  461. si = info->si;
  462. /* sunlight? */
  463. if ( si->sun != NULL && nss[ 0 ] != '1' ) {
  464. Sys_FPrintf( SYS_VRB, "Sun: %s\n", si->shader );
  465. CreateSunLight( si->sun );
  466. si->sun = NULL; /* FIXME: leak! */
  467. }
  468. /* sky light? */
  469. if ( si->skyLightValue > 0.0f ) {
  470. Sys_FPrintf( SYS_VRB, "Sky: %s\n", si->shader );
  471. CreateSkyLights( si->color, si->skyLightValue, si->skyLightIterations, si->lightFilterRadius, si->lightStyle );
  472. si->skyLightValue = 0.0f; /* FIXME: hack! */
  473. }
  474. /* try to early out */
  475. if ( si->value <= 0 ) {
  476. continue;
  477. }
  478. /* autosprite shaders become point lights */
  479. if ( si->autosprite ) {
  480. /* create an average xyz */
  481. VectorAdd( info->mins, info->maxs, origin );
  482. VectorScale( origin, 0.5f, origin );
  483. /* create a light */
  484. light = safe_malloc( sizeof( *light ) );
  485. memset( light, 0, sizeof( *light ) );
  486. light->next = lights;
  487. lights = light;
  488. /* set it up */
  489. light->flags = LIGHT_Q3A_DEFAULT;
  490. light->type = EMIT_POINT;
  491. light->photons = si->value * pointScale;
  492. light->fade = 1.0f;
  493. light->si = si;
  494. VectorCopy( origin, light->origin );
  495. VectorCopy( si->color, light->color );
  496. light->falloffTolerance = falloffTolerance;
  497. light->style = si->lightStyle;
  498. /* add to point light count and continue */
  499. numPointLights++;
  500. continue;
  501. }
  502. /* get subdivision amount */
  503. if ( si->lightSubdivide > 0 ) {
  504. subdivide = si->lightSubdivide;
  505. }
  506. else{
  507. subdivide = defaultLightSubdivide;
  508. }
  509. /* switch on type */
  510. switch ( ds->surfaceType )
  511. {
  512. case MST_PLANAR:
  513. case MST_TRIANGLE_SOUP:
  514. RadLightForTriangles( i, 0, info->lm, si, APPROX_BOUNCE, subdivide, &cw );
  515. break;
  516. case MST_PATCH:
  517. RadLightForPatch( i, 0, info->lm, si, APPROX_BOUNCE, subdivide, &cw );
  518. break;
  519. default:
  520. break;
  521. }
  522. }
  523. }
  524. /*
  525. SetEntityOrigins()
  526. find the offset values for inline models
  527. */
  528. void SetEntityOrigins( void ){
  529. int i, j, k, f;
  530. entity_t *e;
  531. vec3_t origin;
  532. const char *key;
  533. int modelnum;
  534. bspModel_t *dm;
  535. bspDrawSurface_t *ds;
  536. /* ydnar: copy drawverts into private storage for nefarious purposes */
  537. yDrawVerts = safe_malloc( numBSPDrawVerts * sizeof( bspDrawVert_t ) );
  538. memcpy( yDrawVerts, bspDrawVerts, numBSPDrawVerts * sizeof( bspDrawVert_t ) );
  539. /* set the entity origins */
  540. for ( i = 0; i < numEntities; i++ )
  541. {
  542. /* get entity and model */
  543. e = &entities[ i ];
  544. key = ValueForKey( e, "model" );
  545. if ( key[ 0 ] != '*' ) {
  546. continue;
  547. }
  548. modelnum = atoi( key + 1 );
  549. dm = &bspModels[ modelnum ];
  550. /* get entity origin */
  551. key = ValueForKey( e, "origin" );
  552. if ( key[ 0 ] == '\0' ) {
  553. continue;
  554. }
  555. GetVectorForKey( e, "origin", origin );
  556. /* set origin for all surfaces for this model */
  557. for ( j = 0; j < dm->numBSPSurfaces; j++ )
  558. {
  559. /* get drawsurf */
  560. ds = &bspDrawSurfaces[ dm->firstBSPSurface + j ];
  561. /* set its verts */
  562. for ( k = 0; k < ds->numVerts; k++ )
  563. {
  564. f = ds->firstVert + k;
  565. VectorAdd( origin, bspDrawVerts[ f ].xyz, yDrawVerts[ f ].xyz );
  566. }
  567. }
  568. }
  569. }
  570. /*
  571. PointToPolygonFormFactor()
  572. calculates the area over a point/normal hemisphere a winding covers
  573. ydnar: fixme: there has to be a faster way to calculate this
  574. without the expensive per-vert sqrts and transcendental functions
  575. ydnar 2002-09-30: added -faster switch because only 19% deviance > 10%
  576. between this and the approximation
  577. */
  578. #define ONE_OVER_2PI 0.159154942f //% (1.0f / (2.0f * 3.141592657f))
  579. float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ){
  580. vec3_t triVector, triNormal;
  581. int i, j;
  582. vec3_t dirs[ MAX_POINTS_ON_WINDING ];
  583. float total;
  584. float dot, angle, facing;
  585. /* this is expensive */
  586. for ( i = 0; i < w->numpoints; i++ )
  587. {
  588. VectorSubtract( w->p[ i ], point, dirs[ i ] );
  589. VectorNormalize( dirs[ i ], dirs[ i ] );
  590. }
  591. /* duplicate first vertex to avoid mod operation */
  592. VectorCopy( dirs[ 0 ], dirs[ i ] );
  593. /* calculcate relative area */
  594. total = 0.0f;
  595. for ( i = 0; i < w->numpoints; i++ )
  596. {
  597. /* get a triangle */
  598. j = i + 1;
  599. dot = DotProduct( dirs[ i ], dirs[ j ] );
  600. /* roundoff can cause slight creep, which gives an IND from acos */
  601. if ( dot > 1.0f ) {
  602. dot = 1.0f;
  603. }
  604. else if ( dot < -1.0f ) {
  605. dot = -1.0f;
  606. }
  607. /* get the angle */
  608. angle = acos( dot );
  609. CrossProduct( dirs[ i ], dirs[ j ], triVector );
  610. if ( VectorNormalize( triVector, triNormal ) < 0.0001f ) {
  611. continue;
  612. }
  613. facing = DotProduct( normal, triNormal );
  614. total += facing * angle;
  615. /* ydnar: this was throwing too many errors with radiosity + crappy maps. ignoring it. */
  616. if ( total > 6.3f || total < -6.3f ) {
  617. return 0.0f;
  618. }
  619. }
  620. /* now in the range of 0 to 1 over the entire incoming hemisphere */
  621. //% total /= (2.0f * 3.141592657f);
  622. total *= ONE_OVER_2PI;
  623. return total;
  624. }
  625. /*
  626. LightContributionTosample()
  627. determines the amount of light reaching a sample (luxel or vertex) from a given light
  628. */
  629. int LightContributionToSample( trace_t *trace ){
  630. light_t *light;
  631. float angle;
  632. float add;
  633. float dist;
  634. float addDeluxe = 0.0f, addDeluxeBounceScale = 0.25f;
  635. qboolean angledDeluxe = qtrue;
  636. float colorBrightness;
  637. qboolean doAddDeluxe = qtrue;
  638. /* get light */
  639. light = trace->light;
  640. /* clear color */
  641. trace->forceSubsampling = 0.0f; /* to make sure */
  642. VectorClear( trace->color );
  643. VectorClear( trace->colorNoShadow );
  644. VectorClear( trace->directionContribution );
  645. colorBrightness = RGBTOGRAY( light->color ) * ( 1.0f / 255.0f );
  646. /* ydnar: early out */
  647. if ( !( light->flags & LIGHT_SURFACES ) || light->envelope <= 0.0f ) {
  648. return 0;
  649. }
  650. /* do some culling checks */
  651. if ( light->type != EMIT_SUN ) {
  652. /* MrE: if the light is behind the surface */
  653. if ( trace->twoSided == qfalse ) {
  654. if ( DotProduct( light->origin, trace->normal ) - DotProduct( trace->origin, trace->normal ) < 0.0f ) {
  655. return 0;
  656. }
  657. }
  658. /* ydnar: test pvs */
  659. if ( !ClusterVisible( trace->cluster, light->cluster ) ) {
  660. return 0;
  661. }
  662. }
  663. /* exact point to polygon form factor */
  664. if ( light->type == EMIT_AREA ) {
  665. float factor;
  666. float d;
  667. vec3_t pushedOrigin;
  668. /* project sample point into light plane */
  669. d = DotProduct( trace->origin, light->normal ) - light->dist;
  670. if ( d < 3.0f ) {
  671. /* sample point behind plane? */
  672. if ( !( light->flags & LIGHT_TWOSIDED ) && d < -1.0f ) {
  673. return 0;
  674. }
  675. /* sample plane coincident? */
  676. if ( d > -3.0f && DotProduct( trace->normal, light->normal ) > 0.9f ) {
  677. return 0;
  678. }
  679. }
  680. /* nudge the point so that it is clearly forward of the light */
  681. /* so that surfaces meeting a light emitter don't get black edges */
  682. if ( d > -8.0f && d < 8.0f ) {
  683. VectorMA( trace->origin, ( 8.0f - d ), light->normal, pushedOrigin );
  684. }
  685. else{
  686. VectorCopy( trace->origin, pushedOrigin );
  687. }
  688. /* get direction and distance */
  689. VectorCopy( light->origin, trace->end );
  690. dist = SetupTrace( trace );
  691. if ( dist >= light->envelope ) {
  692. return 0;
  693. }
  694. /* ptpff approximation */
  695. if ( faster ) {
  696. /* angle attenuation */
  697. angle = DotProduct( trace->normal, trace->direction );
  698. /* twosided lighting */
  699. if ( trace->twoSided && angle < 0 ) {
  700. angle = -angle;
  701. /* no deluxemap contribution from "other side" light */
  702. doAddDeluxe = qfalse;
  703. }
  704. /* attenuate */
  705. angle *= -DotProduct( light->normal, trace->direction );
  706. if ( angle == 0.0f ) {
  707. return 0;
  708. }
  709. else if ( angle < 0.0f &&
  710. ( trace->twoSided || ( light->flags & LIGHT_TWOSIDED ) ) ) {
  711. angle = -angle;
  712. /* no deluxemap contribution from "other side" light */
  713. doAddDeluxe = qfalse;
  714. }
  715. /* clamp the distance to prevent super hot spots */
  716. dist = sqrt( dist * dist + light->extraDist * light->extraDist );
  717. if ( dist < 16.0f ) {
  718. dist = 16.0f;
  719. }
  720. add = light->photons / ( dist * dist ) * angle;
  721. if ( deluxemap ) {
  722. if ( angledDeluxe ) {
  723. addDeluxe = light->photons / ( dist * dist ) * angle;
  724. }
  725. else{
  726. addDeluxe = light->photons / ( dist * dist );
  727. }
  728. }
  729. }
  730. else
  731. {
  732. /* calculate the contribution */
  733. factor = PointToPolygonFormFactor( pushedOrigin, trace->normal, light->w );
  734. if ( factor == 0.0f ) {
  735. return 0;
  736. }
  737. else if ( factor < 0.0f ) {
  738. /* twosided lighting */
  739. if ( trace->twoSided || ( light->flags & LIGHT_TWOSIDED ) ) {
  740. factor = -factor;
  741. /* push light origin to other side of the plane */
  742. VectorMA( light->origin, -2.0f, light->normal, trace->end );
  743. dist = SetupTrace( trace );
  744. if ( dist >= light->envelope ) {
  745. return 0;
  746. }
  747. /* no deluxemap contribution from "other side" light */
  748. doAddDeluxe = qfalse;
  749. }
  750. else{
  751. return 0;
  752. }
  753. }
  754. /* also don't deluxe if the direction is on the wrong side */
  755. if ( DotProduct( trace->normal, trace->direction ) < 0 ) {
  756. /* no deluxemap contribution from "other side" light */
  757. doAddDeluxe = qfalse;
  758. }
  759. /* ydnar: moved to here */
  760. add = factor * light->add;
  761. if ( deluxemap ) {
  762. addDeluxe = add;
  763. }
  764. }
  765. }
  766. /* point/spot lights */
  767. else if ( light->type == EMIT_POINT || light->type == EMIT_SPOT ) {
  768. /* get direction and distance */
  769. VectorCopy( light->origin, trace->end );
  770. dist = SetupTrace( trace );
  771. if ( dist >= light->envelope ) {
  772. return 0;
  773. }
  774. /* clamp the distance to prevent super hot spots */
  775. dist = sqrt( dist * dist + light->extraDist * light->extraDist );
  776. if ( dist < 16.0f ) {
  777. dist = 16.0f;
  778. }
  779. /* angle attenuation */
  780. if ( light->flags & LIGHT_ATTEN_ANGLE ) {
  781. /* standard Lambert attenuation */
  782. float dot = DotProduct( trace->normal, trace->direction );
  783. /* twosided lighting */
  784. if ( trace->twoSided && dot < 0 ) {
  785. dot = -dot;
  786. /* no deluxemap contribution from "other side" light */
  787. doAddDeluxe = qfalse;
  788. }
  789. /* jal: optional half Lambert attenuation (http://developer.valvesoftware.com/wiki/Half_Lambert) */
  790. if ( lightAngleHL ) {
  791. if ( dot > 0.001f ) { // skip coplanar
  792. if ( dot > 1.0f ) {
  793. dot = 1.0f;
  794. }
  795. dot = ( dot * 0.5f ) + 0.5f;
  796. dot *= dot;
  797. }
  798. else{
  799. dot = 0;
  800. }
  801. }
  802. angle = dot;
  803. }
  804. else{
  805. angle = 1.0f;
  806. }
  807. if ( light->angleScale != 0.0f ) {
  808. angle /= light->angleScale;
  809. if ( angle > 1.0f ) {
  810. angle = 1.0f;
  811. }
  812. }
  813. /* attenuate */
  814. if ( light->flags & LIGHT_ATTEN_LINEAR ) {
  815. add = angle * light->photons * linearScale - ( dist * light->fade );
  816. if ( add < 0.0f ) {
  817. add = 0.0f;
  818. }
  819. if ( deluxemap ) {
  820. if ( angledDeluxe ) {
  821. addDeluxe = angle * light->photons * linearScale - ( dist * light->fade );
  822. }
  823. else{
  824. addDeluxe = light->photons * linearScale - ( dist * light->fade );
  825. }
  826. if ( addDeluxe < 0.0f ) {
  827. addDeluxe = 0.0f;
  828. }
  829. }
  830. }
  831. else
  832. {
  833. add = ( light->photons / ( dist * dist ) ) * angle;
  834. if ( add < 0.0f ) {
  835. add = 0.0f;
  836. }
  837. if ( deluxemap ) {
  838. if ( angledDeluxe ) {
  839. addDeluxe = ( light->photons / ( dist * dist ) ) * angle;
  840. }
  841. else{
  842. addDeluxe = ( light->photons / ( dist * dist ) );
  843. }
  844. }
  845. if ( addDeluxe < 0.0f ) {
  846. addDeluxe = 0.0f;
  847. }
  848. }
  849. /* handle spotlights */
  850. if ( light->type == EMIT_SPOT ) {
  851. float distByNormal, radiusAtDist, sampleRadius;
  852. vec3_t pointAtDist, distToSample;
  853. /* do cone calculation */
  854. distByNormal = -DotProduct( trace->displacement, light->normal );
  855. if ( distByNormal < 0.0f ) {
  856. return 0;
  857. }
  858. VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
  859. radiusAtDist = light->radiusByDist * distByNormal;
  860. VectorSubtract( trace->origin, pointAtDist, distToSample );
  861. sampleRadius = VectorLength( distToSample );
  862. /* outside the cone */
  863. if ( sampleRadius >= radiusAtDist ) {
  864. return 0;
  865. }
  866. /* attenuate */
  867. if ( sampleRadius > ( radiusAtDist - 32.0f ) ) {
  868. add *= ( ( radiusAtDist - sampleRadius ) / 32.0f );
  869. if ( add < 0.0f ) {
  870. add = 0.0f;
  871. }
  872. addDeluxe *= ( ( radiusAtDist - sampleRadius ) / 32.0f );
  873. if ( addDeluxe < 0.0f ) {
  874. addDeluxe = 0.0f;
  875. }
  876. }
  877. }
  878. }
  879. /* ydnar: sunlight */
  880. else if ( light->type == EMIT_SUN ) {
  881. /* get origin and direction */
  882. VectorAdd( trace->origin, light->origin, trace->end );
  883. dist = SetupTrace( trace );
  884. /* angle attenuation */
  885. if ( light->flags & LIGHT_ATTEN_ANGLE ) {
  886. /* standard Lambert attenuation */
  887. float dot = DotProduct( trace->normal, trace->direction );
  888. /* twosided lighting */
  889. if ( trace->twoSided && dot < 0 ) {
  890. dot = -dot;
  891. /* no deluxemap contribution from "other side" light */
  892. doAddDeluxe = qfalse;
  893. }
  894. /* jal: optional half Lambert attenuation (http://developer.valvesoftware.com/wiki/Half_Lambert) */
  895. if ( lightAngleHL ) {
  896. if ( dot > 0.001f ) { // skip coplanar
  897. if ( dot > 1.0f ) {
  898. dot = 1.0f;
  899. }
  900. dot = ( dot * 0.5f ) + 0.5f;
  901. dot *= dot;
  902. }
  903. else{
  904. dot = 0;
  905. }
  906. }
  907. angle = dot;
  908. }
  909. else{
  910. angle = 1.0f;
  911. }
  912. /* attenuate */
  913. add = light->photons * angle;
  914. if ( deluxemap ) {
  915. if ( angledDeluxe ) {
  916. addDeluxe = light->photons * angle;
  917. }
  918. else{
  919. addDeluxe = light->photons;
  920. }
  921. if ( addDeluxe < 0.0f ) {
  922. addDeluxe = 0.0f;
  923. }
  924. }
  925. if ( add <= 0.0f ) {
  926. return 0;
  927. }
  928. /* VorteX: set noShadow color */
  929. VectorScale( light->color, add, trace->colorNoShadow );
  930. addDeluxe *= colorBrightness;
  931. if ( bouncing ) {
  932. addDeluxe *= addDeluxeBounceScale;
  933. if ( addDeluxe < 0.00390625f ) {
  934. addDeluxe = 0.00390625f;
  935. }
  936. }
  937. VectorScale( trace->direction, addDeluxe, trace->directionContribution );
  938. /* setup trace */
  939. trace->testAll = qtrue;
  940. VectorScale( light->color, add, trace->color );
  941. /* trace to point */
  942. if ( trace->testOcclusion && !trace->forceSunlight ) {
  943. /* trace */
  944. TraceLine( trace );
  945. trace->forceSubsampling *= add;
  946. if ( !( trace->compileFlags & C_SKY ) || trace->opaque ) {
  947. VectorClear( trace->color );
  948. VectorClear( trace->directionContribution );
  949. return -1;
  950. }
  951. }
  952. /* return to sender */
  953. return 1;
  954. }
  955. else {
  956. Error( "Light of undefined type!" );
  957. }
  958. /* VorteX: set noShadow color */
  959. VectorScale( light->color, add, trace->colorNoShadow );
  960. /* ydnar: changed to a variable number */
  961. if ( add <= 0.0f || ( add <= light->falloffTolerance && ( light->flags & LIGHT_FAST_ACTUAL ) ) ) {
  962. return 0;
  963. }
  964. addDeluxe *= colorBrightness;
  965. /* hack land: scale down the radiosity contribution to light directionality.
  966. Deluxemaps fusion many light directions into one. In a rtl process all lights
  967. would contribute individually to the bump map, so several light sources together
  968. would make it more directional (example: a yellow and red lights received from
  969. opposing sides would light one side in red and the other in blue, adding
  970. the effect of 2 directions applied. In the deluxemapping case, this 2 lights would
  971. neutralize each other making it look like having no direction.
  972. Same thing happens with radiosity. In deluxemapping case the radiosity contribution
  973. is modifying the direction applied from directional lights, making it go closer and closer
  974. to the surface normal the bigger is the amount of radiosity received.
  975. So, for preserving the directional lights contributions, we scale down the radiosity
  976. contribution. It's a hack, but there's a reason behind it */
  977. if ( bouncing ) {
  978. addDeluxe *= addDeluxeBounceScale;
  979. /* better NOT increase it beyond the original value
  980. if( addDeluxe < 0.00390625f )
  981. addDeluxe = 0.00390625f;
  982. */
  983. }
  984. if ( doAddDeluxe ) {
  985. VectorScale( trace->direction, addDeluxe, trace->directionContribution );
  986. }
  987. /* setup trace */
  988. trace->testAll = qfalse;
  989. VectorScale( light->color, add, trace->color );
  990. /* raytrace */
  991. TraceLine( trace );
  992. trace->forceSubsampling *= add;
  993. if ( trace->passSolid || trace->opaque ) {
  994. VectorClear( trace->color );
  995. VectorClear( trace->directionContribution );
  996. return -1;
  997. }
  998. /* return to sender */
  999. return 1;
  1000. }
  1001. /*
  1002. LightingAtSample()
  1003. determines the amount of light reaching a sample (luxel or vertex)
  1004. */
  1005. void LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colors[ MAX_LIGHTMAPS ] ){
  1006. int i, lightmapNum;
  1007. /* clear colors */
  1008. for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
  1009. VectorClear( colors[ lightmapNum ] );
  1010. /* ydnar: normalmap */
  1011. if ( normalmap ) {
  1012. colors[ 0 ][ 0 ] = ( trace->normal[ 0 ] + 1.0f ) * 127.5f;
  1013. colors[ 0 ][ 1 ] = ( trace->normal[ 1 ] + 1.0f ) * 127.5f;
  1014. colors[ 0 ][ 2 ] = ( trace->normal[ 2 ] + 1.0f ) * 127.5f;
  1015. return;
  1016. }
  1017. /* ydnar: don't bounce ambient all the time */
  1018. if ( !bouncing ) {
  1019. VectorCopy( ambientColor, colors[ 0 ] );
  1020. }
  1021. /* ydnar: trace to all the list of lights pre-stored in tw */
  1022. for ( i = 0; i < trace->numLights && trace->lights[ i ] != NULL; i++ )
  1023. {
  1024. /* set light */
  1025. trace->light = trace->lights[ i ];
  1026. /* style check */
  1027. for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
  1028. {
  1029. if ( styles[ lightmapNum ] == trace->light->style ||
  1030. styles[ lightmapNum ] == LS_NONE ) {
  1031. break;
  1032. }
  1033. }
  1034. /* max of MAX_LIGHTMAPS (4) styles allowed to hit a sample */
  1035. if ( lightmapNum >= MAX_LIGHTMAPS ) {
  1036. continue;
  1037. }
  1038. /* sample light */
  1039. LightContributionToSample( trace );
  1040. if ( trace->color[ 0 ] == 0.0f && trace->color[ 1 ] == 0.0f && trace->color[ 2 ] == 0.0f ) {
  1041. continue;
  1042. }
  1043. /* handle negative light */
  1044. if ( trace->light->flags & LIGHT_NEGATIVE ) {
  1045. VectorScale( trace->color, -1.0f, trace->color );
  1046. }
  1047. /* set style */
  1048. styles[ lightmapNum ] = trace->light->style;
  1049. /* add it */
  1050. VectorAdd( colors[ lightmapNum ], trace->color, colors[ lightmapNum ] );
  1051. /* cheap mode */
  1052. if ( cheap &&
  1053. colors[ 0 ][ 0 ] >= 255.0f &&
  1054. colors[ 0 ][ 1 ] >= 255.0f &&
  1055. colors[ 0 ][ 2 ] >= 255.0f ) {
  1056. break;
  1057. }
  1058. }
  1059. }
  1060. /*
  1061. LightContributionToPoint()
  1062. for a given light, how much light/color reaches a given point in space (with no facing)
  1063. note: this is similar to LightContributionToSample() but optimized for omnidirectional sampling
  1064. */
  1065. int LightContributionToPoint( trace_t *trace ){
  1066. light_t *light;
  1067. float add, dist;
  1068. /* get light */
  1069. light = trace->light;
  1070. /* clear color */
  1071. VectorClear( trace->color );
  1072. /* ydnar: early out */
  1073. if ( !( light->flags & LIGHT_GRID ) || light->envelope <= 0.0f ) {
  1074. return qfalse;
  1075. }
  1076. /* is this a sun? */
  1077. if ( light->type != EMIT_SUN ) {
  1078. /* sun only? */
  1079. if ( sunOnly ) {
  1080. return qfalse;
  1081. }
  1082. /* test pvs */
  1083. if ( !ClusterVisible( trace->cluster, light->cluster ) ) {
  1084. return qfalse;
  1085. }
  1086. }
  1087. /* ydnar: check origin against light's pvs envelope */
  1088. if ( trace->origin[ 0 ] > light->maxs[ 0 ] || trace->origin[ 0 ] < light->mins[ 0 ] ||
  1089. trace->origin[ 1 ] > light->maxs[ 1 ] || trace->origin[ 1 ] < light->mins[ 1 ] ||
  1090. trace->origin[ 2 ] > light->maxs[ 2 ] || trace->origin[ 2 ] < light->mins[ 2 ] ) {
  1091. gridBoundsCulled++;
  1092. return qfalse;
  1093. }
  1094. /* set light origin */
  1095. if ( light->type == EMIT_SUN ) {
  1096. VectorAdd( trace->origin, light->origin, trace->end );
  1097. }
  1098. else{
  1099. VectorCopy( light->origin, trace->end );
  1100. }
  1101. /* set direction */
  1102. dist = SetupTrace( trace );
  1103. /* test envelope */
  1104. if ( dist > light->envelope ) {
  1105. gridEnvelopeCulled++;
  1106. return qfalse;
  1107. }
  1108. /* ptpff approximation */
  1109. if ( light->type == EMIT_AREA && faster ) {
  1110. /* clamp the distance to prevent super hot spots */
  1111. dist = sqrt( dist * dist + light->extraDist * light->extraDist );
  1112. if ( dist < 16.0f ) {
  1113. dist = 16.0f;
  1114. }
  1115. /* attenuate */
  1116. add = light->photons / ( dist * dist );
  1117. }
  1118. /* exact point to polygon form factor */
  1119. else if ( light->type == EMIT_AREA ) {
  1120. float factor, d;
  1121. vec3_t pushedOrigin;
  1122. /* see if the point is behind the light */
  1123. d = DotProduct( trace->origin, light->normal ) - light->dist;
  1124. if ( !( light->flags & LIGHT_TWOSIDED ) && d < -1.0f ) {
  1125. return qfalse;
  1126. }
  1127. /* nudge the point so that it is clearly forward of the light */
  1128. /* so that surfaces meeting a light emiter don't get black edges */
  1129. if ( d > -8.0f && d < 8.0f ) {
  1130. VectorMA( trace->origin, ( 8.0f - d ), light->normal, pushedOrigin );
  1131. }
  1132. else{
  1133. VectorCopy( trace->origin, pushedOrigin );
  1134. }
  1135. /* calculate the contribution (ydnar 2002-10-21: [bug 642] bad normal calc) */
  1136. factor = PointToPolygonFormFactor( pushedOrigin, trace->direction, light->w );
  1137. if ( factor == 0.0f ) {
  1138. return qfalse;
  1139. }
  1140. else if ( factor < 0.0f ) {
  1141. if ( light->flags & LIGHT_TWOSIDED ) {
  1142. factor = -factor;
  1143. }
  1144. else{
  1145. return qfalse;
  1146. }
  1147. }
  1148. /* ydnar: moved to here */
  1149. add = factor * light->add;
  1150. }
  1151. /* point/spot lights */
  1152. else if ( light->type == EMIT_POINT || light->type == EMIT_SPOT ) {
  1153. /* clamp the distance to prevent super hot spots */
  1154. dist = sqrt( dist * dist + light->extraDist * light->extraDist );
  1155. if ( dist < 16.0f ) {
  1156. dist = 16.0f;
  1157. }
  1158. /* attenuate */
  1159. if ( light->flags & LIGHT_ATTEN_LINEAR ) {
  1160. add = light->photons * linearScale - ( dist * light->fade );
  1161. if ( add < 0.0f ) {
  1162. add = 0.0f;
  1163. }
  1164. }
  1165. else{
  1166. add = light->photons / ( dist * dist );
  1167. }
  1168. /* handle spotlights */
  1169. if ( light->type == EMIT_SPOT ) {
  1170. float distByNormal, radiusAtDist, sampleRadius;
  1171. vec3_t pointAtDist, distToSample;
  1172. /* do cone calculation */
  1173. distByNormal = -DotProduct( trace->displacement, light->normal );
  1174. if ( distByNormal < 0.0f ) {
  1175. return qfalse;
  1176. }
  1177. VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
  1178. radiusAtDist = light->radiusByDist * distByNormal;
  1179. VectorSubtract( trace->origin, pointAtDist, distToSample );
  1180. sampleRadius = VectorLength( distToSample );
  1181. /* outside the cone */
  1182. if ( sampleRadius >= radiusAtDist ) {
  1183. return qfalse;
  1184. }
  1185. /* attenuate */
  1186. if ( sampleRadius > ( radiusAtDist - 32.0f ) ) {
  1187. add *= ( ( radiusAtDist - sampleRadius ) / 32.0f );
  1188. }
  1189. }
  1190. }
  1191. /* ydnar: sunlight */
  1192. else if ( light->type == EMIT_SUN ) {
  1193. /* attenuate */
  1194. add = light->photons;
  1195. if ( add <= 0.0f ) {
  1196. return qfalse;
  1197. }
  1198. /* setup trace */
  1199. trace->testAll = qtrue;
  1200. VectorScale( light->color, add, trace->color );
  1201. /* trace to point */
  1202. if ( trace->testOcclusion && !trace->forceSunlight ) {
  1203. /* trace */
  1204. TraceLine( trace );
  1205. if ( !( trace->compileFlags & C_SKY ) || trace->opaque ) {
  1206. VectorClear( trace->color );
  1207. return -1;
  1208. }
  1209. }
  1210. /* return to sender */
  1211. return qtrue;
  1212. }
  1213. /* unknown light type */
  1214. else{
  1215. return qfalse;
  1216. }
  1217. /* ydnar: changed to a variable number */
  1218. if ( add <= 0.0f || ( add <= light->falloffTolerance && ( light->flags & LIGHT_FAST_ACTUAL ) ) ) {
  1219. return qfalse;
  1220. }
  1221. /* setup trace */
  1222. trace->testAll = qfalse;
  1223. VectorScale( light->color, add, trace->color );
  1224. /* trace */
  1225. TraceLine( trace );
  1226. if ( trace->passSolid ) {
  1227. VectorClear( trace->color );
  1228. return qfalse;
  1229. }
  1230. /* we have a valid sample */
  1231. return qtrue;
  1232. }
  1233. /*
  1234. TraceGrid()
  1235. grid samples are for quickly determining the lighting
  1236. of dynamically placed entities in the world
  1237. */
  1238. #define MAX_CONTRIBUTIONS 32768
  1239. typedef struct
  1240. {
  1241. vec3_t dir;
  1242. vec3_t color;
  1243. vec3_t ambient;
  1244. int style;
  1245. }
  1246. contribution_t;
  1247. void TraceGrid( int num ){
  1248. int i, j, x, y, z, mod, numCon, numStyles;
  1249. float d, step;
  1250. vec3_t baseOrigin, cheapColor, color, thisdir;
  1251. rawGridPoint_t *gp;
  1252. bspGridPoint_t *bgp;
  1253. contribution_t contributions[ MAX_CONTRIBUTIONS ];
  1254. trace_t trace;
  1255. /* get grid points */
  1256. gp = &rawGridPoints[ num ];
  1257. bgp = &bspGridPoints[ num ];
  1258. /* get grid origin */
  1259. mod = num;
  1260. z = mod / ( gridBounds[ 0 ] * gridBounds[ 1 ] );
  1261. mod -= z * ( gridBounds[ 0 ] * gridBounds[ 1 ] );
  1262. y = mod / gridBounds[ 0 ];
  1263. mod -= y * gridBounds[ 0 ];
  1264. x = mod;
  1265. trace.origin[ 0 ] = gridMins[ 0 ] + x * gridSize[ 0 ];
  1266. trace.origin[ 1 ] = gridMins[ 1 ] + y * gridSize[ 1 ];
  1267. trace.origin[ 2 ] = gridMins[ 2 ] + z * gridSize[ 2 ];
  1268. /* set inhibit sphere */
  1269. if ( gridSize[ 0 ] > gridSize[ 1 ] && gridSize[ 0 ] > gridSize[ 2 ] ) {
  1270. trace.inhibitRadius = gridSize[ 0 ] * 0.5f;
  1271. }
  1272. else if ( gridSize[ 1 ] > gridSize[ 0 ] && gridSize[ 1 ] > gridSize[ 2 ] ) {
  1273. trace.inhibitRadius = gridSize[ 1 ] * 0.5f;
  1274. }
  1275. else{
  1276. trace.inhibitRadius = gridSize[ 2 ] * 0.5f;
  1277. }
  1278. /* find point cluster */
  1279. trace.cluster = ClusterForPointExt( trace.origin, GRID_EPSILON );
  1280. if ( trace.cluster < 0 ) {
  1281. /* try to nudge the origin around to find a valid point */
  1282. VectorCopy( trace.origin, baseOrigin );
  1283. for ( step = 0; ( step += 0.005 ) <= 1.0; )
  1284. {
  1285. VectorCopy( baseOrigin, trace.origin );
  1286. trace.origin[ 0 ] += step * ( Random() - 0.5 ) * gridSize[0];
  1287. trace.origin[ 1 ] += step * ( Random() - 0.5 ) * gridSize[1];
  1288. trace.origin[ 2 ] += step * ( Random() - 0.5 ) * gridSize[2];
  1289. /* ydnar: changed to find cluster num */
  1290. trace.cluster = ClusterForPointExt( trace.origin, VERTEX_EPSILON );
  1291. if ( trace.cluster >= 0 ) {
  1292. break;
  1293. }
  1294. }
  1295. /* can't find a valid point at all */
  1296. if ( step > 1.0 ) {
  1297. return;
  1298. }
  1299. }
  1300. /* setup trace */
  1301. trace.testOcclusion = !noTrace;
  1302. trace.forceSunlight = qfalse;
  1303. trace.recvShadows = WORLDSPAWN_RECV_SHADOWS;
  1304. trace.numSurfaces = 0;
  1305. trace.surfaces = NULL;
  1306. trace.numLights = 0;
  1307. trace.lights = NULL;
  1308. /* clear */
  1309. numCon = 0;
  1310. VectorClear( cheapColor );
  1311. /* trace to all the lights, find the major light direction, and divide the
  1312. total light between that along the direction and the remaining in the ambient */
  1313. for ( trace.light = lights; trace.light != NULL; trace.light = trace.light->next )
  1314. {
  1315. float addSize;
  1316. /* sample light */
  1317. if ( !LightContributionToPoint( &trace ) ) {
  1318. continue;
  1319. }
  1320. /* handle negative light */
  1321. if ( trace.light->flags & LIGHT_NEGATIVE ) {
  1322. VectorScale( trace.color, -1.0f, trace.color );
  1323. }
  1324. /* add a contribution */
  1325. VectorCopy( trace.color, contributions[ numCon ].color );
  1326. VectorCopy( trace.direction, contributions[ numCon ].dir );
  1327. VectorClear( contributions[ numCon ].ambient );
  1328. contributions[ numCon ].style = trace.light->style;
  1329. numCon++;
  1330. /* push average direction around */
  1331. addSize = VectorLength( trace.color );
  1332. VectorMA( gp->dir, addSize, trace.direction, gp->dir );
  1333. /* stop after a while */
  1334. if ( numCon >= ( MAX_CONTRIBUTIONS - 1 ) ) {
  1335. break;
  1336. }
  1337. /* ydnar: cheap mode */
  1338. VectorAdd( cheapColor, trace.color, cheapColor );
  1339. if ( cheapgrid && cheapColor[ 0 ] >= 255.0f && cheapColor[ 1 ] >= 255.0f && cheapColor[ 2 ] >= 255.0f ) {
  1340. break;
  1341. }
  1342. }
  1343. /////// Floodlighting for point //////////////////
  1344. //do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
  1345. if ( floodlighty ) {
  1346. int k;
  1347. float addSize, f;
  1348. vec3_t dir = { 0, 0, 1 };
  1349. float ambientFrac = 0.25f;
  1350. trace.testOcclusion = qtrue;
  1351. trace.forceSunlight = qfalse;
  1352. trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
  1353. trace.testAll = qtrue;
  1354. for ( k = 0; k < 2; k++ )
  1355. {
  1356. if ( k == 0 ) { // upper hemisphere
  1357. trace.normal[0] = 0;
  1358. trace.normal[1] = 0;
  1359. trace.normal[2] = 1;
  1360. }
  1361. else //lower hemisphere
  1362. {
  1363. trace.normal[0] = 0;
  1364. trace.normal[1] = 0;
  1365. trace.normal[2] = -1;
  1366. }
  1367. f = FloodLightForSample( &trace, floodlightDistance, floodlight_lowquality );
  1368. /* add a fraction as pure ambient, half as top-down direction */
  1369. contributions[ numCon ].color[0] = floodlightRGB[0] * floodlightIntensity * f * ( 1.0f - ambientFrac );
  1370. contributions[ numCon ].color[1] = floodlightRGB[1] * floodlightIntensity * f * ( 1.0f - ambientFrac );
  1371. contributions[ numCon ].color[2] = floodlightRGB[2] * floodlightIntensity * f * ( 1.0f - ambientFrac );
  1372. contributions[ numCon ].ambient[0] = floodlightRGB[0] * floodlightIntensity * f * ambientFrac;
  1373. contributions[ numCon ].ambient[1] = floodlightRGB[1] * floodlightIntensity * f * ambientFrac;
  1374. contributions[ numCon ].ambient[2] = floodlightRGB[2] * floodlightIntensity * f * ambientFrac;
  1375. contributions[ numCon ].dir[0] = dir[0];
  1376. contributions[ numCon ].dir[1] = dir[1];
  1377. contributions[ numCon ].dir[2] = dir[2];
  1378. contributions[ numCon ].style = 0;
  1379. /* push average direction around */
  1380. addSize = VectorLength( contributions[ numCon ].color );
  1381. VectorMA( gp->dir, addSize, dir, gp->dir );
  1382. numCon++;
  1383. }
  1384. }
  1385. /////////////////////
  1386. /* normalize to get primary light direction */
  1387. VectorNormalize( gp->dir, thisdir );
  1388. /* now that we have identified the primary light direction,
  1389. go back and separate all the light into directed and ambient */
  1390. numStyles = 1;
  1391. for ( i = 0; i < numCon; i++ )
  1392. {
  1393. /* get relative directed strength */
  1394. d = DotProduct( contributions[ i ].dir, thisdir );
  1395. /* we map 1 to gridDirectionality, and 0 to gridAmbientDirectionality */
  1396. d = gridAmbientDirectionality + d * ( gridDirectionality - gridAmbientDirectionality );
  1397. if ( d < 0.0f ) {
  1398. d = 0.0f;
  1399. }
  1400. /* find appropriate style */
  1401. for ( j = 0; j < numStyles; j++ )
  1402. {
  1403. if ( gp->styles[ j ] == contributions[ i ].style ) {
  1404. break;
  1405. }
  1406. }
  1407. /* style not found? */
  1408. if ( j >= numStyles ) {
  1409. /* add a new style */
  1410. if ( numStyles < MAX_LIGHTMAPS ) {
  1411. gp->styles[ numStyles ] = contributions[ i ].style;
  1412. bgp->styles[ numStyles ] = contributions[ i ].style;
  1413. numStyles++;
  1414. //% Sys_Printf( "(%d, %d) ", num, contributions[ i ].style );
  1415. }
  1416. /* fallback */
  1417. else{
  1418. j = 0;
  1419. }
  1420. }
  1421. /* add the directed color */
  1422. VectorMA( gp->directed[ j ], d, contributions[ i ].color, gp->directed[ j ] );
  1423. /* ambient light will be at 1/4 the value of directed light */
  1424. /* (ydnar: nuke this in favor of more dramatic lighting?) */
  1425. /* (PM: how about actually making it work? d=1 when it got here for single lights/sun :P */
  1426. // d = 0.25f;
  1427. /* (Hobbes: always setting it to .25 is hardly any better) */
  1428. d = 0.25f * ( 1.0f - d );
  1429. VectorMA( gp->ambient[ j ], d, contributions[ i ].color, gp->ambient[ j ] );
  1430. VectorAdd( gp->ambient[ j ], contributions[ i ].ambient, gp->ambient[ j ] );
  1431. /*
  1432. * div0:
  1433. * the total light average = ambient value + 0.25 * sum of all directional values
  1434. * we can also get the total light average as 0.25 * the sum of all contributions
  1435. *
  1436. * 0.25 * sum(contribution_i) == ambient + 0.25 * sum(d_i contribution_i)
  1437. *
  1438. * THIS YIELDS:
  1439. * ambient == 0.25 * sum((1 - d_i) contribution_i)
  1440. *
  1441. * So, 0.25f * (1.0f - d) IS RIGHT. If you want to tune it, tune d BEFORE.
  1442. */
  1443. }
  1444. /* store off sample */
  1445. for ( i = 0; i < MAX_LIGHTMAPS; i++ )
  1446. {
  1447. #if 0
  1448. /* do some fudging to keep the ambient from being too low (2003-07-05: 0.25 -> 0.125) */
  1449. if ( !bouncing ) {
  1450. VectorMA( gp->ambient[ i ], 0.125f, gp->directed[ i ], gp->ambient[ i ] );
  1451. }
  1452. #endif
  1453. /* set minimum light and copy off to bytes */
  1454. VectorCopy( gp->ambient[ i ], color );
  1455. for ( j = 0; j < 3; j++ )
  1456. if ( color[ j ] < minGridLight[ j ] ) {
  1457. color[ j ] = minGridLight[ j ];
  1458. }
  1459. /* vortex: apply gridscale and gridambientscale here */
  1460. ColorToBytes( color, bgp->ambient[ i ], gridScale * gridAmbientScale );
  1461. ColorToBytes( gp->directed[ i ], bgp->directed[ i ], gridScale );
  1462. }
  1463. /* debug code */
  1464. #if 0
  1465. //% Sys_FPrintf( SYS_VRB, "%10d %10d %10d ", &gp->ambient[ 0 ][ 0 ], &gp->ambient[ 0 ][ 1 ], &gp->ambient[ 0 ][ 2 ] );
  1466. Sys_FPrintf( SYS_VRB, "%9d Amb: (%03.1f %03.1f %03.1f) Dir: (%03.1f %03.1f %03.1f)\n",
  1467. num,
  1468. gp->ambient[ 0 ][ 0 ], gp->ambient[ 0 ][ 1 ], gp->ambient[ 0 ][ 2 ],
  1469. gp->directed[ 0 ][ 0 ], gp->directed[ 0 ][ 1 ], gp->directed[ 0 ][ 2 ] );
  1470. #endif
  1471. /* store direction */
  1472. NormalToLatLong( thisdir, bgp->latLong );
  1473. }
  1474. /*
  1475. SetupGrid()
  1476. calculates the size of the lightgrid and allocates memory
  1477. */
  1478. void SetupGrid( void ){
  1479. int i, j;
  1480. vec3_t maxs, oldGridSize;
  1481. const char *value;
  1482. char temp[ 64 ];
  1483. /* don't do this if not grid lighting */
  1484. if ( noGridLighting ) {
  1485. return;
  1486. }
  1487. /* ydnar: set grid size */
  1488. value = ValueForKey( &entities[ 0 ], "gridsize" );
  1489. if ( value[ 0 ] != '\0' ) {
  1490. sscanf( value, "%f %f %f", &gridSize[ 0 ], &gridSize[ 1 ], &gridSize[ 2 ] );
  1491. }
  1492. /* quantize it */
  1493. VectorCopy( gridSize, oldGridSize );
  1494. for ( i = 0; i < 3; i++ )
  1495. gridSize[ i ] = gridSize[ i ] >= 8.0f ? floor( gridSize[ i ] ) : 8.0f;
  1496. /* ydnar: increase gridSize until grid count is smaller than max allowed */
  1497. numRawGridPoints = MAX_MAP_LIGHTGRID + 1;
  1498. j = 0;
  1499. while ( numRawGridPoints > MAX_MAP_LIGHTGRID )
  1500. {
  1501. /* get world bounds */
  1502. for ( i = 0; i < 3; i++ )
  1503. {
  1504. gridMins[ i ] = gridSize[ i ] * ceil( bspModels[ 0 ].mins[ i ] / gridSize[ i ] );
  1505. maxs[ i ] = gridSize[ i ] * floor( bspModels[ 0 ].maxs[ i ] / gridSize[ i ] );
  1506. gridBounds[ i ] = ( maxs[ i ] - gridMins[ i ] ) / gridSize[ i ] + 1;
  1507. }
  1508. /* set grid size */
  1509. numRawGridPoints = gridBounds[ 0 ] * gridBounds[ 1 ] * gridBounds[ 2 ];
  1510. /* increase grid size a bit */
  1511. if ( numRawGridPoints > MAX_MAP_LIGHTGRID ) {
  1512. gridSize[ j++ % 3 ] += 16.0f;
  1513. }
  1514. }
  1515. /* print it */
  1516. Sys_Printf( "Grid size = { %1.0f, %1.0f, %1.0f }\n", gridSize[ 0 ], gridSize[ 1 ], gridSize[ 2 ] );
  1517. /* different? */
  1518. if ( !VectorCompare( gridSize, oldGridSize ) ) {
  1519. sprintf( temp, "%.0f %.0f %.0f", gridSize[ 0 ], gridSize[ 1 ], gridSize[ 2 ] );
  1520. SetKeyValue( &entities[ 0 ], "gridsize", (const char*) temp );
  1521. Sys_FPrintf( SYS_VRB, "Storing adjusted grid size\n" );
  1522. }
  1523. /* 2nd variable. fixme: is this silly? */
  1524. numBSPGridPoints = numRawGridPoints;
  1525. /* allocate lightgrid */
  1526. rawGridPoints = safe_malloc( numRawGridPoints * sizeof( *rawGridPoints ) );
  1527. memset( rawGridPoints, 0, numRawGridPoints * sizeof( *rawGridPoints ) );
  1528. if ( bspGridPoints != NULL ) {
  1529. free( bspGridPoints );
  1530. }
  1531. bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
  1532. memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
  1533. /* clear lightgrid */
  1534. for ( i = 0; i < numRawGridPoints; i++ )
  1535. {
  1536. VectorCopy( ambientColor, rawGridPoints[ i ].ambient[ j ] );
  1537. rawGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
  1538. bspGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
  1539. for ( j = 1; j < MAX_LIGHTMAPS; j++ )
  1540. {
  1541. rawGridPoints[ i ].styles[ j ] = LS_NONE;
  1542. bspGridPoints[ i ].styles[ j ] = LS_NONE;
  1543. }
  1544. }
  1545. /* note it */
  1546. Sys_Printf( "%9d grid points\n", numRawGridPoints );
  1547. }
  1548. /*
  1549. LightWorld()
  1550. does what it says...
  1551. */
  1552. void LightWorld( const char *BSPFilePath, qboolean fastAllocate ){
  1553. vec3_t color;
  1554. float f;
  1555. int b, bt;
  1556. qboolean minVertex, minGrid;
  1557. const char *value;
  1558. /* ydnar: smooth normals */
  1559. if ( shade ) {
  1560. Sys_Printf( "--- SmoothNormals ---\n" );
  1561. SmoothNormals();
  1562. }
  1563. /* determine the number of grid points */
  1564. Sys_Printf( "--- SetupGrid ---\n" );
  1565. SetupGrid();
  1566. /* find the optional minimum lighting values */
  1567. GetVectorForKey( &entities[ 0 ], "_color", color );
  1568. if ( VectorLength( color ) == 0.0f ) {
  1569. VectorSet( color, 1.0, 1.0, 1.0 );
  1570. }
  1571. if ( colorsRGB ) {
  1572. color[0] = Image_LinearFloatFromsRGBFloat( color[0] );
  1573. color[1] = Image_LinearFloatFromsRGBFloat( color[1] );
  1574. color[2] = Image_LinearFloatFromsRGBFloat( color[2] );
  1575. }
  1576. /* ambient */
  1577. f = FloatForKey( &entities[ 0 ], "_ambient" );
  1578. if ( f == 0.0f ) {
  1579. f = FloatForKey( &entities[ 0 ], "ambient" );
  1580. }
  1581. VectorScale( color, f, ambientColor );
  1582. /* minvertexlight */
  1583. minVertex = qfalse;
  1584. value = ValueForKey( &entities[ 0 ], "_minvertexlight" );
  1585. if ( value[ 0 ] != '\0' ) {
  1586. minVertex = qtrue;
  1587. f = atof( value );
  1588. VectorScale( color, f, minVertexLight );
  1589. }
  1590. /* mingridlight */
  1591. minGrid = qfalse;
  1592. value = ValueForKey( &entities[ 0 ], "_mingridlight" );
  1593. if ( value[ 0 ] != '\0' ) {
  1594. minGrid = qtrue;
  1595. f = atof( value );
  1596. VectorScale( color, f, minGridLight );
  1597. }
  1598. /* minlight */
  1599. value = ValueForKey( &entities[ 0 ], "_minlight" );
  1600. if ( value[ 0 ] != '\0' ) {
  1601. f = atof( value );
  1602. VectorScale( color, f, minLight );
  1603. if ( minVertex == qfalse ) {
  1604. VectorScale( color, f, minVertexLight );
  1605. }
  1606. if ( minGrid == qfalse ) {
  1607. VectorScale( c

Large files files are truncated, but you can click here to view the full file