fog.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  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. #include "qbsp.h"
  19. int c_fogFragment;
  20. int c_fogPatchFragments;
  21. /*
  22. ====================
  23. DrawSurfToMesh
  24. ====================
  25. */
  26. mesh_t *DrawSurfToMesh( mapDrawSurface_t *ds ) {
  27. mesh_t *m;
  28. m = malloc( sizeof( *m ) );
  29. m->width = ds->patchWidth;
  30. m->height = ds->patchHeight;
  31. m->verts = malloc( sizeof(m->verts[0]) * m->width * m->height );
  32. memcpy( m->verts, ds->verts, sizeof(m->verts[0]) * m->width * m->height );
  33. return m;
  34. }
  35. /*
  36. ====================
  37. SplitMeshByPlane
  38. ====================
  39. */
  40. void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back ) {
  41. int w, h, split;
  42. float d[MAX_PATCH_SIZE][MAX_PATCH_SIZE];
  43. drawVert_t *dv, *v1, *v2;
  44. int c_front, c_back, c_on;
  45. mesh_t *f, *b;
  46. int i;
  47. float frac;
  48. int frontAprox, backAprox;
  49. for ( i = 0 ; i < 2 ; i++ ) {
  50. dv = in->verts;
  51. c_front = 0;
  52. c_back = 0;
  53. c_on = 0;
  54. for ( h = 0 ; h < in->height ; h++ ) {
  55. for ( w = 0 ; w < in->width ; w++, dv++ ) {
  56. d[h][w] = DotProduct( dv->xyz, normal ) - dist;
  57. if ( d[h][w] > ON_EPSILON ) {
  58. c_front++;
  59. } else if ( d[h][w] < -ON_EPSILON ) {
  60. c_back++;
  61. } else {
  62. c_on++;
  63. }
  64. }
  65. }
  66. *front = NULL;
  67. *back = NULL;
  68. if ( !c_front ) {
  69. *back = in;
  70. return;
  71. }
  72. if ( !c_back ) {
  73. *front = in;
  74. return;
  75. }
  76. // find a split point
  77. split = -1;
  78. for ( w = 0 ; w < in->width -1 ; w++ ) {
  79. if ( ( d[0][w] < 0 ) != ( d[0][w+1] < 0 ) ) {
  80. if ( split == -1 ) {
  81. split = w;
  82. break;
  83. }
  84. }
  85. }
  86. if ( split == -1 ) {
  87. if ( i == 1 ) {
  88. qprintf( "No crossing points in patch\n");
  89. *front = in;
  90. return;
  91. }
  92. in = TransposeMesh( in );
  93. InvertMesh( in );
  94. continue;
  95. }
  96. // make sure the split point stays the same for all other rows
  97. for ( h = 1 ; h < in->height ; h++ ) {
  98. for ( w = 0 ; w < in->width -1 ; w++ ) {
  99. if ( ( d[h][w] < 0 ) != ( d[h][w+1] < 0 ) ) {
  100. if ( w != split ) {
  101. _printf( "multiple crossing points for patch -- can't clip\n");
  102. *front = in;
  103. return;
  104. }
  105. }
  106. }
  107. if ( ( d[h][split] < 0 ) == ( d[h][split+1] < 0 ) ) {
  108. _printf( "differing crossing points for patch -- can't clip\n");
  109. *front = in;
  110. return;
  111. }
  112. }
  113. break;
  114. }
  115. // create two new meshes
  116. f = malloc( sizeof( *f ) );
  117. f->width = split + 2;
  118. if ( ! (f->width & 1) ) {
  119. f->width++;
  120. frontAprox = 1;
  121. } else {
  122. frontAprox = 0;
  123. }
  124. if ( f->width > MAX_PATCH_SIZE ) {
  125. Error( "MAX_PATCH_SIZE after split");
  126. }
  127. f->height = in->height;
  128. f->verts = malloc( sizeof(f->verts[0]) * f->width * f->height );
  129. b = malloc( sizeof( *b ) );
  130. b->width = in->width - split;
  131. if ( ! (b->width & 1) ) {
  132. b->width++;
  133. backAprox = 1;
  134. } else {
  135. backAprox = 0;
  136. }
  137. if ( b->width > MAX_PATCH_SIZE ) {
  138. Error( "MAX_PATCH_SIZE after split");
  139. }
  140. b->height = in->height;
  141. b->verts = malloc( sizeof(b->verts[0]) * b->width * b->height );
  142. if ( d[0][0] > 0 ) {
  143. *front = f;
  144. *back = b;
  145. } else {
  146. *front = b;
  147. *back = f;
  148. }
  149. // distribute the points
  150. for ( w = 0 ; w < in->width ; w++ ) {
  151. for ( h = 0 ; h < in->height ; h++ ) {
  152. if ( w <= split ) {
  153. f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ];
  154. } else {
  155. b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ];
  156. }
  157. }
  158. }
  159. // clip the crossing line
  160. for ( h = 0 ; h < in->height ; h++ ) {
  161. dv = &f->verts[ h * f->width + split + 1 ];
  162. v1 = &in->verts[ h * in->width + split ];
  163. v2 = &in->verts[ h * in->width + split + 1 ];
  164. frac = d[h][split] / ( d[h][split] - d[h][split+1] );
  165. for ( i = 0 ; i < 10 ; i++ ) {
  166. dv->xyz[i] = v1->xyz[i] + frac * ( v2->xyz[i] - v1->xyz[i] );
  167. }
  168. dv->xyz[10] = 0;//set all 4 colors to 0
  169. if ( frontAprox ) {
  170. f->verts[ h * f->width + split + 2 ] = *dv;
  171. }
  172. b->verts[ h * b->width ] = *dv;
  173. if ( backAprox ) {
  174. b->verts[ h * b->width + 1 ] = *dv;
  175. }
  176. }
  177. /*
  178. PrintMesh( in );
  179. _printf("\n");
  180. PrintMesh( f );
  181. _printf("\n");
  182. PrintMesh( b );
  183. _printf("\n");
  184. */
  185. FreeMesh( in );
  186. }
  187. /*
  188. ====================
  189. ChopPatchByBrush
  190. ====================
  191. */
  192. qboolean ChopPatchByBrush( mapDrawSurface_t *ds, bspbrush_t *b ) {
  193. int i, j;
  194. side_t *s;
  195. plane_t *plane;
  196. mesh_t *outside[MAX_BRUSH_SIDES];
  197. int numOutside;
  198. mesh_t *m, *front, *back;
  199. mapDrawSurface_t *newds;
  200. m = DrawSurfToMesh( ds );
  201. numOutside = 0;
  202. // only split by the top and bottom planes to avoid
  203. // some messy patch clipping issues
  204. for ( i = 4 ; i <= 5 ; i++ ) {
  205. s = &b->sides[ i ];
  206. plane = &mapplanes[ s->planenum ];
  207. SplitMeshByPlane( m, plane->normal, plane->dist, &front, &back );
  208. if ( !back ) {
  209. // nothing actually contained inside
  210. for ( j = 0 ; j < numOutside ; j++ ) {
  211. FreeMesh( outside[j] );
  212. }
  213. return qfalse;
  214. }
  215. m = back;
  216. if ( front ) {
  217. if ( numOutside == MAX_BRUSH_SIDES ) {
  218. Error( "MAX_BRUSH_SIDES" );
  219. }
  220. outside[ numOutside ] = front;
  221. numOutside++;
  222. }
  223. }
  224. // all of outside fragments become seperate drawsurfs
  225. c_fogPatchFragments += numOutside;
  226. for ( i = 0 ; i < numOutside ; i++ ) {
  227. newds = DrawSurfaceForMesh( outside[ i ] );
  228. newds->shaderInfo = ds->shaderInfo;
  229. FreeMesh( outside[ i ] );
  230. }
  231. // replace ds with m
  232. ds->patchWidth = m->width;
  233. ds->patchHeight = m->height;
  234. ds->numVerts = m->width * m->height;
  235. free( ds->verts );
  236. ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
  237. memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
  238. FreeMesh( m );
  239. return qtrue;
  240. }
  241. //===============================================================================
  242. /*
  243. ====================
  244. WindingFromDrawSurf
  245. ====================
  246. */
  247. winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ) {
  248. winding_t *w;
  249. int i;
  250. w = AllocWinding( ds->numVerts );
  251. w->numpoints = ds->numVerts;
  252. for ( i = 0 ; i < ds->numVerts ; i++ ) {
  253. VectorCopy( ds->verts[i].xyz, w->p[i] );
  254. }
  255. return w;
  256. }
  257. /*
  258. ====================
  259. ChopFaceByBrush
  260. There may be a fragment contained in the brush
  261. ====================
  262. */
  263. qboolean ChopFaceByBrush( mapDrawSurface_t *ds, bspbrush_t *b ) {
  264. int i, j;
  265. side_t *s;
  266. plane_t *plane;
  267. winding_t *w;
  268. winding_t *front, *back;
  269. winding_t *outside[MAX_BRUSH_SIDES];
  270. int numOutside;
  271. mapDrawSurface_t *newds;
  272. drawVert_t *dv;
  273. shaderInfo_t *si;
  274. float mins[2];
  275. // brush primitive :
  276. // axis base
  277. vec3_t texX,texY;
  278. vec_t x,y;
  279. w = WindingFromDrawSurf( ds );
  280. numOutside = 0;
  281. for ( i = 0 ; i < b->numsides ; i++ ) {
  282. s = &b->sides[ i ];
  283. if ( s->backSide ) {
  284. continue;
  285. }
  286. plane = &mapplanes[ s->planenum ];
  287. // handle coplanar outfacing (don't fog)
  288. if ( ds->side->planenum == s->planenum ) {
  289. return qfalse;
  290. }
  291. // handle coplanar infacing (keep inside)
  292. if ( ( ds->side->planenum ^ 1 ) == s->planenum ) {
  293. continue;
  294. }
  295. // general case
  296. ClipWindingEpsilon( w, plane->normal, plane->dist, ON_EPSILON,
  297. &front, &back );
  298. FreeWinding( w );
  299. if ( !back ) {
  300. // nothing actually contained inside
  301. for ( j = 0 ; j < numOutside ; j++ ) {
  302. FreeWinding( outside[j] );
  303. }
  304. return qfalse;
  305. }
  306. if ( front ) {
  307. if ( numOutside == MAX_BRUSH_SIDES ) {
  308. Error( "MAX_BRUSH_SIDES" );
  309. }
  310. outside[ numOutside ] = front;
  311. numOutside++;
  312. }
  313. w = back;
  314. }
  315. // all of outside fragments become seperate drawsurfs
  316. // linked to the same side
  317. c_fogFragment += numOutside;
  318. s = ds->side;
  319. for ( i = 0 ; i < numOutside ; i++ ) {
  320. newds = DrawSurfaceForSide( ds->mapBrush, s, outside[i] );
  321. FreeWinding( outside[i] );
  322. }
  323. // replace ds->verts with the verts for w
  324. ds->numVerts = w->numpoints;
  325. free( ds->verts );
  326. ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
  327. memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
  328. si = s->shaderInfo;
  329. mins[0] = 9999;
  330. mins[1] = 9999;
  331. // compute s/t coordinates from brush primitive texture matrix
  332. // compute axis base
  333. ComputeAxisBase( mapplanes[s->planenum].normal, texX, texY );
  334. for ( j = 0 ; j < w->numpoints ; j++ ) {
  335. dv = ds->verts + j;
  336. VectorCopy( w->p[j], dv->xyz );
  337. if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
  338. {
  339. // calculate texture s/t
  340. dv->st[0] = s->vecs[0][3] + DotProduct( s->vecs[0], dv->xyz );
  341. dv->st[1] = s->vecs[1][3] + DotProduct( s->vecs[1], dv->xyz );
  342. dv->st[0] /= si->width;
  343. dv->st[1] /= si->height;
  344. }
  345. else
  346. {
  347. // calculate texture s/t from brush primitive texture matrix
  348. x = DotProduct( dv->xyz, texX );
  349. y = DotProduct( dv->xyz, texY );
  350. dv->st[0]=s->texMat[0][0]*x+s->texMat[0][1]*y+s->texMat[0][2];
  351. dv->st[1]=s->texMat[1][0]*x+s->texMat[1][1]*y+s->texMat[1][2];
  352. }
  353. if ( dv->st[0] < mins[0] ) {
  354. mins[0] = dv->st[0];
  355. }
  356. if ( dv->st[1] < mins[1] ) {
  357. mins[1] = dv->st[1];
  358. }
  359. // copy normal
  360. VectorCopy ( mapplanes[s->planenum].normal, dv->normal );
  361. }
  362. // adjust the texture coordinates to be as close to 0 as possible
  363. if ( !si->globalTexture ) {
  364. mins[0] = floor( mins[0] );
  365. mins[1] = floor( mins[1] );
  366. for ( i = 0 ; i < w->numpoints ; i++ ) {
  367. dv = ds->verts + i;
  368. dv->st[0] -= mins[0];
  369. dv->st[1] -= mins[1];
  370. }
  371. }
  372. return qtrue;
  373. }
  374. //===============================================================================
  375. /*
  376. =====================
  377. FogDrawSurfs
  378. Call after the surface list has been pruned,
  379. before tjunction fixing
  380. before lightmap allocation
  381. =====================
  382. */
  383. void FogDrawSurfs( void ) {
  384. int i, j, k;
  385. mapDrawSurface_t *ds;
  386. bspbrush_t *b;
  387. vec3_t mins, maxs;
  388. int c_fogged;
  389. int numBaseDrawSurfs;
  390. dfog_t *fog;
  391. qprintf("----- FogDrawsurfs -----\n");
  392. c_fogged = 0;
  393. c_fogFragment = 0;
  394. // find all fog brushes
  395. for ( b = entities[0].brushes ; b ; b = b->next ) {
  396. if ( !(b->contents & CONTENTS_FOG) ) {
  397. continue;
  398. }
  399. if ( numFogs == MAX_MAP_FOGS ) {
  400. Error( "MAX_MAP_FOGS" );
  401. }
  402. fog = &dfogs[numFogs];
  403. numFogs++;
  404. fog->brushNum = b->outputNumber;
  405. // find a side with a valid shaderInfo
  406. // non-axial fog columns may have bevel planes that need to be skipped
  407. for ( i = 0 ; i < b->numsides ; i++ ) {
  408. if ( b->sides[i].shaderInfo && (b->sides[i].shaderInfo->contents & CONTENTS_FOG) ) {
  409. strcpy( fog->shader, b->sides[i].shaderInfo->shader );
  410. break;
  411. }
  412. }
  413. if ( i == b->numsides ) {
  414. continue; // shouldn't happen
  415. }
  416. fog->visibleSide = -1;
  417. // clip each surface into this, but don't clip any of
  418. // the resulting fragments to the same brush
  419. numBaseDrawSurfs = numMapDrawSurfs;
  420. for ( i = 0 ; i < numBaseDrawSurfs ; i++ ) {
  421. ds = &mapDrawSurfs[i];
  422. // bound the drawsurf
  423. ClearBounds( mins, maxs );
  424. for ( j = 0 ; j < ds->numVerts ; j++ ) {
  425. AddPointToBounds( ds->verts[j].xyz, mins, maxs );
  426. }
  427. // check against the fog brush
  428. for ( k = 0 ; k < 3 ; k++ ) {
  429. if ( mins[k] > b->maxs[k] ) {
  430. break;
  431. }
  432. if ( maxs[k] < b->mins[k] ) {
  433. break;
  434. }
  435. }
  436. if ( k < 3 ) {
  437. continue; // bboxes don't intersect
  438. }
  439. if ( ds->mapBrush == b ) {
  440. int s;
  441. s = ds->side - b->sides;
  442. if ( s <= 6 ) { // not one of the reversed inside faces
  443. // this is a visible fog plane
  444. if ( fog->visibleSide != -1 ) {
  445. _printf( "WARNING: fog brush %i has multiple visible sides\n", b->brushnum );
  446. }
  447. fog->visibleSide = s;
  448. }
  449. }
  450. if ( ds->miscModel ) {
  451. // we could write splitting code for trimodels if we wanted to...
  452. c_fogged++;
  453. ds->fogNum = numFogs - 1;
  454. } else if ( ds->patch ) {
  455. if ( ChopPatchByBrush( ds, b ) ) {
  456. c_fogged++;
  457. ds->fogNum = numFogs - 1;
  458. }
  459. } else {
  460. if ( ChopFaceByBrush( ds, b ) ) {
  461. c_fogged++;
  462. ds->fogNum = numFogs - 1;
  463. }
  464. }
  465. }
  466. }
  467. // split the drawsurfs by the fog brushes
  468. qprintf( "%5i fogs\n", numFogs );
  469. qprintf( "%5i fog polygon fragments\n", c_fogFragment );
  470. qprintf( "%5i fog patch fragments\n", c_fogPatchFragments );
  471. qprintf( "%5i fogged drawsurfs\n", c_fogged );
  472. }