Interaction.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. /*
  24. ===========================================================================
  25. idInteraction implementation
  26. ===========================================================================
  27. */
  28. /*
  29. ================
  30. R_CalcInteractionFacing
  31. Determines which triangles of the surface are facing towards the light origin.
  32. The facing array should be allocated with one extra index than
  33. the number of surface triangles, which will be used to handle dangling
  34. edge silhouettes.
  35. ================
  36. */
  37. void R_CalcInteractionFacing( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo ) {
  38. SCOPED_PROFILE_EVENT( "R_CalcInteractionFacing" );
  39. if ( cullInfo.facing != NULL ) {
  40. return;
  41. }
  42. idVec3 localLightOrigin;
  43. R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
  44. const int numFaces = tri->numIndexes / 3;
  45. cullInfo.facing = (byte *) R_StaticAlloc( ( numFaces + 1 ) * sizeof( cullInfo.facing[0] ), TAG_RENDER_INTERACTION );
  46. // exact geometric cull against face
  47. for ( int i = 0, face = 0; i < tri->numIndexes; i += 3, face++ ) {
  48. const idDrawVert & v0 = tri->verts[tri->indexes[i + 0]];
  49. const idDrawVert & v1 = tri->verts[tri->indexes[i + 1]];
  50. const idDrawVert & v2 = tri->verts[tri->indexes[i + 2]];
  51. const idPlane plane( v0.xyz, v1.xyz, v2.xyz );
  52. const float d = plane.Distance( localLightOrigin );
  53. cullInfo.facing[face] = ( d >= 0.0f );
  54. }
  55. cullInfo.facing[numFaces] = 1; // for dangling edges to reference
  56. }
  57. /*
  58. =====================
  59. R_CalcInteractionCullBits
  60. We want to cull a little on the sloppy side, because the pre-clipping
  61. of geometry to the lights in dmap will give many cases that are right
  62. at the border. We throw things out on the border, because if any one
  63. vertex is clearly inside, the entire triangle will be accepted.
  64. =====================
  65. */
  66. void R_CalcInteractionCullBits( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo ) {
  67. SCOPED_PROFILE_EVENT( "R_CalcInteractionCullBits" );
  68. if ( cullInfo.cullBits != NULL ) {
  69. return;
  70. }
  71. idPlane frustumPlanes[6];
  72. idRenderMatrix::GetFrustumPlanes( frustumPlanes, light->baseLightProject, true, true );
  73. int frontBits = 0;
  74. // cull the triangle surface bounding box
  75. for ( int i = 0; i < 6; i++ ) {
  76. R_GlobalPlaneToLocal( ent->modelMatrix, frustumPlanes[i], cullInfo.localClipPlanes[i] );
  77. // get front bits for the whole surface
  78. if ( tri->bounds.PlaneDistance( cullInfo.localClipPlanes[i] ) >= LIGHT_CLIP_EPSILON ) {
  79. frontBits |= 1 << i;
  80. }
  81. }
  82. // if the surface is completely inside the light frustum
  83. if ( frontBits == ( ( 1 << 6 ) - 1 ) ) {
  84. cullInfo.cullBits = LIGHT_CULL_ALL_FRONT;
  85. return;
  86. }
  87. cullInfo.cullBits = (byte *) R_StaticAlloc( tri->numVerts * sizeof( cullInfo.cullBits[0] ), TAG_RENDER_INTERACTION );
  88. memset( cullInfo.cullBits, 0, tri->numVerts * sizeof( cullInfo.cullBits[0] ) );
  89. for ( int i = 0; i < 6; i++ ) {
  90. // if completely infront of this clipping plane
  91. if ( frontBits & ( 1 << i ) ) {
  92. continue;
  93. }
  94. for ( int j = 0; j < tri->numVerts; j++ ) {
  95. float d = cullInfo.localClipPlanes[i].Distance( tri->verts[j].xyz );
  96. cullInfo.cullBits[j] |= ( d < LIGHT_CLIP_EPSILON ) << i;
  97. }
  98. }
  99. }
  100. /*
  101. ================
  102. R_FreeInteractionCullInfo
  103. ================
  104. */
  105. void R_FreeInteractionCullInfo( srfCullInfo_t &cullInfo ) {
  106. if ( cullInfo.facing != NULL ) {
  107. R_StaticFree( cullInfo.facing );
  108. cullInfo.facing = NULL;
  109. }
  110. if ( cullInfo.cullBits != NULL ) {
  111. if ( cullInfo.cullBits != LIGHT_CULL_ALL_FRONT ) {
  112. R_StaticFree( cullInfo.cullBits );
  113. }
  114. cullInfo.cullBits = NULL;
  115. }
  116. }
  117. /*
  118. ====================
  119. R_CreateInteractionLightTris
  120. This is only used for the static interaction case, dynamic interactions
  121. just draw everything and let the GPU deal with it.
  122. The resulting surface will be a subset of the original triangles,
  123. it will never clip triangles, but it may cull on a per-triangle basis.
  124. ====================
  125. */
  126. static srfTriangles_t *R_CreateInteractionLightTris( const idRenderEntityLocal *ent,
  127. const srfTriangles_t *tri, const idRenderLightLocal *light,
  128. const idMaterial *shader ) {
  129. SCOPED_PROFILE_EVENT( "R_CreateInteractionLightTris" );
  130. int i;
  131. int numIndexes;
  132. triIndex_t *indexes;
  133. srfTriangles_t *newTri;
  134. int c_backfaced;
  135. int c_distance;
  136. idBounds bounds;
  137. bool includeBackFaces;
  138. int faceNum;
  139. c_backfaced = 0;
  140. c_distance = 0;
  141. numIndexes = 0;
  142. indexes = NULL;
  143. // it is debatable if non-shadowing lights should light back faces. we aren't at the moment
  144. if ( r_lightAllBackFaces.GetBool() || light->lightShader->LightEffectsBackSides()
  145. || shader->ReceivesLightingOnBackSides() || ent->parms.noSelfShadow || ent->parms.noShadow ) {
  146. includeBackFaces = true;
  147. } else {
  148. includeBackFaces = false;
  149. }
  150. // allocate a new surface for the lit triangles
  151. newTri = R_AllocStaticTriSurf();
  152. // save a reference to the original surface
  153. newTri->ambientSurface = const_cast<srfTriangles_t *>(tri);
  154. // the light surface references the verts of the ambient surface
  155. newTri->numVerts = tri->numVerts;
  156. R_ReferenceStaticTriSurfVerts( newTri, tri );
  157. // calculate cull information
  158. srfCullInfo_t cullInfo = {};
  159. if ( !includeBackFaces ) {
  160. R_CalcInteractionFacing( ent, tri, light, cullInfo );
  161. }
  162. R_CalcInteractionCullBits( ent, tri, light, cullInfo );
  163. // if the surface is completely inside the light frustum
  164. if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT ) {
  165. // if we aren't self shadowing, let back facing triangles get
  166. // through so the smooth shaded bump maps light all the way around
  167. if ( includeBackFaces ) {
  168. // the whole surface is lit so the light surface just references the indexes of the ambient surface
  169. newTri->indexes = tri->indexes;
  170. newTri->indexCache = tri->indexCache;
  171. // R_ReferenceStaticTriSurfIndexes( newTri, tri );
  172. numIndexes = tri->numIndexes;
  173. bounds = tri->bounds;
  174. } else {
  175. // the light tris indexes are going to be a subset of the original indexes so we generally
  176. // allocate too much memory here but we decrease the memory block when the number of indexes is known
  177. R_AllocStaticTriSurfIndexes( newTri, tri->numIndexes );
  178. // back face cull the individual triangles
  179. indexes = newTri->indexes;
  180. const byte *facing = cullInfo.facing;
  181. for ( faceNum = i = 0; i < tri->numIndexes; i += 3, faceNum++ ) {
  182. if ( !facing[ faceNum ] ) {
  183. c_backfaced++;
  184. continue;
  185. }
  186. indexes[numIndexes+0] = tri->indexes[i+0];
  187. indexes[numIndexes+1] = tri->indexes[i+1];
  188. indexes[numIndexes+2] = tri->indexes[i+2];
  189. numIndexes += 3;
  190. }
  191. // get bounds for the surface
  192. SIMDProcessor->MinMax( bounds[0], bounds[1], tri->verts, indexes, numIndexes );
  193. // decrease the size of the memory block to the size of the number of used indexes
  194. newTri->numIndexes = numIndexes;
  195. R_ResizeStaticTriSurfIndexes( newTri, numIndexes );
  196. }
  197. } else {
  198. // the light tris indexes are going to be a subset of the original indexes so we generally
  199. // allocate too much memory here but we decrease the memory block when the number of indexes is known
  200. R_AllocStaticTriSurfIndexes( newTri, tri->numIndexes );
  201. // cull individual triangles
  202. indexes = newTri->indexes;
  203. const byte *facing = cullInfo.facing;
  204. const byte *cullBits = cullInfo.cullBits;
  205. for ( faceNum = i = 0; i < tri->numIndexes; i += 3, faceNum++ ) {
  206. int i1, i2, i3;
  207. // if we aren't self shadowing, let back facing triangles get
  208. // through so the smooth shaded bump maps light all the way around
  209. if ( !includeBackFaces ) {
  210. // back face cull
  211. if ( !facing[ faceNum ] ) {
  212. c_backfaced++;
  213. continue;
  214. }
  215. }
  216. i1 = tri->indexes[i+0];
  217. i2 = tri->indexes[i+1];
  218. i3 = tri->indexes[i+2];
  219. // fast cull outside the frustum
  220. // if all three points are off one plane side, it definately isn't visible
  221. if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
  222. c_distance++;
  223. continue;
  224. }
  225. // add to the list
  226. indexes[numIndexes+0] = i1;
  227. indexes[numIndexes+1] = i2;
  228. indexes[numIndexes+2] = i3;
  229. numIndexes += 3;
  230. }
  231. // get bounds for the surface
  232. SIMDProcessor->MinMax( bounds[0], bounds[1], tri->verts, indexes, numIndexes );
  233. // decrease the size of the memory block to the size of the number of used indexes
  234. newTri->numIndexes = numIndexes;
  235. R_ResizeStaticTriSurfIndexes( newTri, numIndexes );
  236. }
  237. // free the cull information when it's no longer needed
  238. R_FreeInteractionCullInfo( cullInfo );
  239. if ( !numIndexes ) {
  240. R_FreeStaticTriSurf( newTri );
  241. return NULL;
  242. }
  243. newTri->numIndexes = numIndexes;
  244. newTri->bounds = bounds;
  245. return newTri;
  246. }
  247. /*
  248. =====================
  249. R_CreateInteractionShadowVolume
  250. Note that dangling edges outside the light frustum don't make silhouette planes because
  251. a triangle outside the light frustum is considered facing and the "fake triangle" on
  252. the outside of the dangling edge is also set to facing: cullInfo.facing[numFaces] = 1;
  253. =====================
  254. */
  255. static srfTriangles_t *R_CreateInteractionShadowVolume( const idRenderEntityLocal * ent,
  256. const srfTriangles_t * tri, const idRenderLightLocal * light ) {
  257. SCOPED_PROFILE_EVENT( "R_CreateInteractionShadowVolume" );
  258. srfCullInfo_t cullInfo = {};
  259. R_CalcInteractionFacing( ent, tri, light, cullInfo );
  260. R_CalcInteractionCullBits( ent, tri, light, cullInfo );
  261. int numFaces = tri->numIndexes / 3;
  262. int numShadowingFaces = 0;
  263. const byte * facing = cullInfo.facing;
  264. // if all the triangles are inside the light frustum
  265. if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT ) {
  266. // count the number of shadowing faces
  267. for ( int i = 0; i < numFaces; i++ ) {
  268. numShadowingFaces += facing[i];
  269. }
  270. numShadowingFaces = numFaces - numShadowingFaces;
  271. } else {
  272. // make all triangles that are outside the light frustum "facing", so they won't cast shadows
  273. const triIndex_t * indexes = tri->indexes;
  274. byte *modifyFacing = cullInfo.facing;
  275. const byte *cullBits = cullInfo.cullBits;
  276. for ( int i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
  277. if ( !modifyFacing[j] ) {
  278. int i1 = indexes[i+0];
  279. int i2 = indexes[i+1];
  280. int i3 = indexes[i+2];
  281. if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
  282. modifyFacing[j] = 1;
  283. } else {
  284. numShadowingFaces++;
  285. }
  286. }
  287. }
  288. }
  289. if ( !numShadowingFaces ) {
  290. // no faces are inside the light frustum and still facing the right way
  291. R_FreeInteractionCullInfo( cullInfo );
  292. return NULL;
  293. }
  294. // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
  295. srfTriangles_t * newTri = R_AllocStaticTriSurf();
  296. newTri->numVerts = tri->numVerts * 2;
  297. // alloc the max possible size
  298. R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
  299. triIndex_t * tempIndexes = newTri->indexes;
  300. triIndex_t * shadowIndexes = newTri->indexes;
  301. // create new triangles along sil planes
  302. const silEdge_t * sil = tri->silEdges;
  303. for ( int i = tri->numSilEdges; i > 0; i--, sil++ ) {
  304. int f1 = facing[sil->p1];
  305. int f2 = facing[sil->p2];
  306. if ( !( f1 ^ f2 ) ) {
  307. continue;
  308. }
  309. int v1 = sil->v1 << 1;
  310. int v2 = sil->v2 << 1;
  311. // set the two triangle winding orders based on facing
  312. // without using a poorly-predictable branch
  313. shadowIndexes[0] = v1;
  314. shadowIndexes[1] = v2 ^ f1;
  315. shadowIndexes[2] = v2 ^ f2;
  316. shadowIndexes[3] = v1 ^ f2;
  317. shadowIndexes[4] = v1 ^ f1;
  318. shadowIndexes[5] = v2 ^ 1;
  319. shadowIndexes += 6;
  320. }
  321. int numShadowIndexes = shadowIndexes - tempIndexes;
  322. // we aren't bothering to separate front and back caps on these
  323. newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
  324. newTri->numShadowIndexesNoCaps = numShadowIndexes;
  325. newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
  326. // decrease the size of the memory block to only store the used indexes
  327. // R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
  328. // these have no effect, because they extend to infinity
  329. newTri->bounds.Clear();
  330. // put some faces on the model and some on the distant projection
  331. const triIndex_t * indexes = tri->indexes;
  332. shadowIndexes = newTri->indexes + numShadowIndexes;
  333. for ( int i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
  334. if ( facing[j] ) {
  335. continue;
  336. }
  337. int i0 = indexes[i+0] << 1;
  338. int i1 = indexes[i+1] << 1;
  339. int i2 = indexes[i+2] << 1;
  340. shadowIndexes[0] = i2;
  341. shadowIndexes[1] = i1;
  342. shadowIndexes[2] = i0;
  343. shadowIndexes[3] = i0 ^ 1;
  344. shadowIndexes[4] = i1 ^ 1;
  345. shadowIndexes[5] = i2 ^ 1;
  346. shadowIndexes += 6;
  347. }
  348. R_FreeInteractionCullInfo( cullInfo );
  349. return newTri;
  350. }
  351. /*
  352. ===============
  353. idInteraction::idInteraction
  354. ===============
  355. */
  356. idInteraction::idInteraction() {
  357. numSurfaces = 0;
  358. surfaces = NULL;
  359. entityDef = NULL;
  360. lightDef = NULL;
  361. lightNext = NULL;
  362. lightPrev = NULL;
  363. entityNext = NULL;
  364. entityPrev = NULL;
  365. staticInteraction = false;
  366. }
  367. /*
  368. ===============
  369. idInteraction::AllocAndLink
  370. ===============
  371. */
  372. idInteraction *idInteraction::AllocAndLink( idRenderEntityLocal *edef, idRenderLightLocal *ldef ) {
  373. if ( edef == NULL || ldef == NULL ) {
  374. common->Error( "idInteraction::AllocAndLink: NULL parm" );
  375. return NULL;
  376. }
  377. idRenderWorldLocal *renderWorld = edef->world;
  378. idInteraction *interaction = renderWorld->interactionAllocator.Alloc();
  379. // link and initialize
  380. interaction->lightDef = ldef;
  381. interaction->entityDef = edef;
  382. interaction->numSurfaces = -1; // not checked yet
  383. interaction->surfaces = NULL;
  384. // link at the start of the entity's list
  385. interaction->lightNext = ldef->firstInteraction;
  386. interaction->lightPrev = NULL;
  387. ldef->firstInteraction = interaction;
  388. if ( interaction->lightNext != NULL ) {
  389. interaction->lightNext->lightPrev = interaction;
  390. } else {
  391. ldef->lastInteraction = interaction;
  392. }
  393. // link at the start of the light's list
  394. interaction->entityNext = edef->firstInteraction;
  395. interaction->entityPrev = NULL;
  396. edef->firstInteraction = interaction;
  397. if ( interaction->entityNext != NULL ) {
  398. interaction->entityNext->entityPrev = interaction;
  399. } else {
  400. edef->lastInteraction = interaction;
  401. }
  402. // update the interaction table
  403. if ( renderWorld->interactionTable != NULL ) {
  404. int index = ldef->index * renderWorld->interactionTableWidth + edef->index;
  405. if ( renderWorld->interactionTable[index] != NULL ) {
  406. common->Error( "idInteraction::AllocAndLink: non NULL table entry" );
  407. }
  408. renderWorld->interactionTable[ index ] = interaction;
  409. }
  410. return interaction;
  411. }
  412. /*
  413. ===============
  414. idInteraction::FreeSurfaces
  415. Frees the surfaces, but leaves the interaction linked in, so it
  416. will be regenerated automatically
  417. ===============
  418. */
  419. void idInteraction::FreeSurfaces() {
  420. // anything regenerated is no longer an optimized static version
  421. this->staticInteraction = false;
  422. if ( this->surfaces != NULL ) {
  423. for ( int i = 0; i < this->numSurfaces; i++ ) {
  424. surfaceInteraction_t &srf = this->surfaces[i];
  425. Mem_Free( srf.shadowIndexes );
  426. srf.shadowIndexes = NULL;
  427. }
  428. R_StaticFree( this->surfaces );
  429. this->surfaces = NULL;
  430. }
  431. this->numSurfaces = -1;
  432. }
  433. /*
  434. ===============
  435. idInteraction::Unlink
  436. ===============
  437. */
  438. void idInteraction::Unlink() {
  439. // unlink from the entity's list
  440. if ( this->entityPrev ) {
  441. this->entityPrev->entityNext = this->entityNext;
  442. } else {
  443. this->entityDef->firstInteraction = this->entityNext;
  444. }
  445. if ( this->entityNext ) {
  446. this->entityNext->entityPrev = this->entityPrev;
  447. } else {
  448. this->entityDef->lastInteraction = this->entityPrev;
  449. }
  450. this->entityNext = this->entityPrev = NULL;
  451. // unlink from the light's list
  452. if ( this->lightPrev ) {
  453. this->lightPrev->lightNext = this->lightNext;
  454. } else {
  455. this->lightDef->firstInteraction = this->lightNext;
  456. }
  457. if ( this->lightNext ) {
  458. this->lightNext->lightPrev = this->lightPrev;
  459. } else {
  460. this->lightDef->lastInteraction = this->lightPrev;
  461. }
  462. this->lightNext = this->lightPrev = NULL;
  463. }
  464. /*
  465. ===============
  466. idInteraction::UnlinkAndFree
  467. Removes links and puts it back on the free list.
  468. ===============
  469. */
  470. void idInteraction::UnlinkAndFree() {
  471. // clear the table pointer
  472. idRenderWorldLocal *renderWorld = this->lightDef->world;
  473. int index = this->lightDef->index * renderWorld->interactionTableWidth + this->entityDef->index;
  474. if ( renderWorld->interactionTable[index] != this && renderWorld->interactionTable[index] != INTERACTION_EMPTY ) {
  475. common->Error( "idInteraction::UnlinkAndFree: interactionTable wasn't set" );
  476. }
  477. renderWorld->interactionTable[index] = NULL;
  478. Unlink();
  479. FreeSurfaces();
  480. // put it back on the free list
  481. renderWorld->interactionAllocator.Free( this );
  482. }
  483. /*
  484. ===============
  485. idInteraction::MakeEmpty
  486. Relinks the interaction at the end of both the light and entity chains
  487. and adds the INTERACTION_EMPTY marker to the interactionTable.
  488. It is necessary to keep the empty interaction so when entities or lights move
  489. they can set all the interactionTable values to NULL.
  490. ===============
  491. */
  492. void idInteraction::MakeEmpty() {
  493. // an empty interaction has no surfaces
  494. numSurfaces = 0;
  495. Unlink();
  496. // relink at the end of the entity's list
  497. this->entityNext = NULL;
  498. this->entityPrev = this->entityDef->lastInteraction;
  499. this->entityDef->lastInteraction = this;
  500. if ( this->entityPrev ) {
  501. this->entityPrev->entityNext = this;
  502. } else {
  503. this->entityDef->firstInteraction = this;
  504. }
  505. // relink at the end of the light's list
  506. this->lightNext = NULL;
  507. this->lightPrev = this->lightDef->lastInteraction;
  508. this->lightDef->lastInteraction = this;
  509. if ( this->lightPrev ) {
  510. this->lightPrev->lightNext = this;
  511. } else {
  512. this->lightDef->firstInteraction = this;
  513. }
  514. // store the special marker in the interaction table
  515. const int interactionIndex = lightDef->index * entityDef->world->interactionTableWidth + entityDef->index;
  516. assert( entityDef->world->interactionTable[ interactionIndex ] == this );
  517. entityDef->world->interactionTable[ interactionIndex ] = INTERACTION_EMPTY;
  518. }
  519. /*
  520. ===============
  521. idInteraction::HasShadows
  522. ===============
  523. */
  524. bool idInteraction::HasShadows() const {
  525. return !entityDef->parms.noShadow && lightDef->LightCastsShadows();
  526. }
  527. /*
  528. ======================
  529. CreateStaticInteraction
  530. Called by idRenderWorldLocal::GenerateAllInteractions
  531. ======================
  532. */
  533. void idInteraction::CreateStaticInteraction() {
  534. // note that it is a static interaction
  535. staticInteraction = true;
  536. const idRenderModel *model = entityDef->parms.hModel;
  537. if ( model == NULL || model->NumSurfaces() <= 0 || model->IsDynamicModel() != DM_STATIC ) {
  538. MakeEmpty();
  539. return;
  540. }
  541. const idBounds bounds = model->Bounds( &entityDef->parms );
  542. // if it doesn't contact the light frustum, none of the surfaces will
  543. if ( R_CullModelBoundsToLight( lightDef, bounds, entityDef->modelRenderMatrix ) ) {
  544. MakeEmpty();
  545. return;
  546. }
  547. //
  548. // create slots for each of the model's surfaces
  549. //
  550. numSurfaces = model->NumSurfaces();
  551. surfaces = (surfaceInteraction_t *)R_ClearedStaticAlloc( sizeof( *surfaces ) * numSurfaces );
  552. bool interactionGenerated = false;
  553. // check each surface in the model
  554. for ( int c = 0 ; c < model->NumSurfaces() ; c++ ) {
  555. const modelSurface_t * surf = model->Surface( c );
  556. const srfTriangles_t * tri = surf->geometry;
  557. if ( tri == NULL ) {
  558. continue;
  559. }
  560. // determine the shader for this surface, possibly by skinning
  561. // Note that this will be wrong if customSkin/customShader are
  562. // changed after map load time without invalidating the interaction!
  563. const idMaterial * const shader = R_RemapShaderBySkin( surf->shader,
  564. entityDef->parms.customSkin, entityDef->parms.customShader );
  565. if ( shader == NULL ) {
  566. continue;
  567. }
  568. // try to cull each surface
  569. if ( R_CullModelBoundsToLight( lightDef, tri->bounds, entityDef->modelRenderMatrix ) ) {
  570. continue;
  571. }
  572. surfaceInteraction_t *sint = &surfaces[c];
  573. // generate a set of indexes for the lit surfaces, culling away triangles that are
  574. // not at least partially inside the light
  575. if ( shader->ReceivesLighting() ) {
  576. srfTriangles_t * lightTris = R_CreateInteractionLightTris( entityDef, tri, lightDef, shader );
  577. if ( lightTris != NULL ) {
  578. // make a static index cache
  579. sint->numLightTrisIndexes = lightTris->numIndexes;
  580. sint->lightTrisIndexCache = vertexCache.AllocStaticIndex( lightTris->indexes, ALIGN( lightTris->numIndexes * sizeof( lightTris->indexes[0] ), INDEX_CACHE_ALIGN ) );
  581. interactionGenerated = true;
  582. R_FreeStaticTriSurf( lightTris );
  583. }
  584. }
  585. // if the interaction has shadows and this surface casts a shadow
  586. if ( HasShadows() && shader->SurfaceCastsShadow() && tri->silEdges != NULL ) {
  587. // if the light has an optimized shadow volume, don't create shadows for any models that are part of the base areas
  588. if ( lightDef->parms.prelightModel == NULL || !model->IsStaticWorldModel() || r_skipPrelightShadows.GetBool() ) {
  589. srfTriangles_t * shadowTris = R_CreateInteractionShadowVolume( entityDef, tri, lightDef );
  590. if ( shadowTris != NULL ) {
  591. // make a static index cache
  592. sint->shadowIndexCache = vertexCache.AllocStaticIndex( shadowTris->indexes, ALIGN( shadowTris->numIndexes * sizeof( shadowTris->indexes[0] ), INDEX_CACHE_ALIGN ) );
  593. sint->numShadowIndexes = shadowTris->numIndexes;
  594. #if defined( KEEP_INTERACTION_CPU_DATA )
  595. sint->shadowIndexes = shadowTris->indexes;
  596. shadowTris->indexes = NULL;
  597. #endif
  598. if ( shader->Coverage() != MC_OPAQUE ) {
  599. // if any surface is a shadow-casting perforated or translucent surface, or the
  600. // base surface is suppressed in the view (world weapon shadows) we can't use
  601. // the external shadow optimizations because we can see through some of the faces
  602. sint->numShadowIndexesNoCaps = shadowTris->numIndexes;
  603. } else {
  604. sint->numShadowIndexesNoCaps = shadowTris->numShadowIndexesNoCaps;
  605. }
  606. R_FreeStaticTriSurf( shadowTris );
  607. }
  608. interactionGenerated = true;
  609. }
  610. }
  611. }
  612. // if none of the surfaces generated anything, don't even bother checking?
  613. if ( !interactionGenerated ) {
  614. MakeEmpty();
  615. }
  616. }
  617. /*
  618. ===================
  619. R_ShowInteractionMemory_f
  620. ===================
  621. */
  622. void R_ShowInteractionMemory_f( const idCmdArgs &args ) {
  623. int entities = 0;
  624. int interactions = 0;
  625. int deferredInteractions = 0;
  626. int emptyInteractions = 0;
  627. int lightTris = 0;
  628. int lightTriIndexes = 0;
  629. int shadowTris = 0;
  630. int shadowTriIndexes = 0;
  631. int maxInteractionsForEntity = 0;
  632. int maxInteractionsForLight = 0;
  633. for ( int i = 0; i < tr.primaryWorld->lightDefs.Num(); i++ ) {
  634. idRenderLightLocal * light = tr.primaryWorld->lightDefs[i];
  635. if ( light == NULL ) {
  636. continue;
  637. }
  638. int numInteractionsForLight = 0;
  639. for ( idInteraction *inter = light->firstInteraction; inter != NULL; inter = inter->lightNext ) {
  640. if ( !inter->IsEmpty() ) {
  641. numInteractionsForLight++;
  642. }
  643. }
  644. if ( numInteractionsForLight > maxInteractionsForLight ) {
  645. maxInteractionsForLight = numInteractionsForLight;
  646. }
  647. }
  648. for ( int i = 0; i < tr.primaryWorld->entityDefs.Num(); i++ ) {
  649. idRenderEntityLocal *def = tr.primaryWorld->entityDefs[i];
  650. if ( def == NULL ) {
  651. continue;
  652. }
  653. if ( def->firstInteraction == NULL ) {
  654. continue;
  655. }
  656. entities++;
  657. int numInteractionsForEntity = 0;
  658. for ( idInteraction *inter = def->firstInteraction; inter != NULL; inter = inter->entityNext ) {
  659. interactions++;
  660. if ( !inter->IsEmpty() ) {
  661. numInteractionsForEntity++;
  662. }
  663. if ( inter->IsDeferred() ) {
  664. deferredInteractions++;
  665. continue;
  666. }
  667. if ( inter->IsEmpty() ) {
  668. emptyInteractions++;
  669. continue;
  670. }
  671. for ( int j = 0; j < inter->numSurfaces; j++ ) {
  672. surfaceInteraction_t *srf = &inter->surfaces[j];
  673. if ( srf->numLightTrisIndexes ) {
  674. lightTris++;
  675. lightTriIndexes += srf->numLightTrisIndexes;
  676. }
  677. if ( srf->numShadowIndexes ) {
  678. shadowTris++;
  679. shadowTriIndexes += srf->numShadowIndexes;
  680. }
  681. }
  682. }
  683. if ( numInteractionsForEntity > maxInteractionsForEntity ) {
  684. maxInteractionsForEntity = numInteractionsForEntity;
  685. }
  686. }
  687. common->Printf( "%i entities with %i total interactions\n", entities, interactions );
  688. common->Printf( "%i deferred interactions, %i empty interactions\n", deferredInteractions, emptyInteractions );
  689. common->Printf( "%5i indexes in %5i light tris\n", lightTriIndexes, lightTris );
  690. common->Printf( "%5i indexes in %5i shadow tris\n", shadowTriIndexes, shadowTris );
  691. common->Printf( "%i maxInteractionsForEntity\n", maxInteractionsForEntity );
  692. common->Printf( "%i maxInteractionsForLight\n", maxInteractionsForLight );
  693. }