SECTORFX.CPP 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. #include <stdlib.h>
  2. #include "engine.h"
  3. #include "sectorfx.h"
  4. #include "globals.h"
  5. #include "db.h"
  6. #include "misc.h"
  7. #include "trig.h"
  8. #include "debug4g.h"
  9. #include <memcheck.h>
  10. #define kPanScale 8
  11. short shadeList[kMaxXSectors];
  12. short panList[kMaxXSectors];
  13. int shadeCount = 0, panCount = 0;
  14. short wallPanList[kMaxXSectors];
  15. int wallPanCount = 0;
  16. int gDepth[] =
  17. {
  18. 0, // kDepthWalk
  19. 15 << 8, // kDepthTread
  20. 30 << 8, // kDepthWade
  21. 40 << 8 // kDepthSwim
  22. };
  23. // monotonic flicker -- very doom like
  24. static char flicker1[] = {
  25. 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0,
  26. 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1,
  27. 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
  28. 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1,
  29. };
  30. // organic flicker -- good for torches
  31. static char flicker2[] = {
  32. 1, 2, 4, 2, 3, 4, 3, 2, 0, 0, 1, 2, 4, 3, 2, 0,
  33. 2, 1, 0, 1, 0, 2, 3, 4, 3, 2, 1, 1, 2, 0, 0, 1,
  34. 1, 2, 3, 4, 4, 3, 2, 1, 2, 3, 4, 4, 2, 1, 0, 1,
  35. 0, 0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2,
  36. };
  37. // mostly on flicker -- good for flaky fluourescents
  38. static char flicker3[] = {
  39. 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 2, 4, 3, 4, 4,
  40. 4, 4, 2, 1, 3, 3, 3, 4, 3, 4, 4, 4, 4, 4, 2, 4,
  41. 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 0, 1,
  42. 0, 1, 0, 1, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 4,
  43. };
  44. // not yet done (same as 2 for now)
  45. static char flicker4[] = {
  46. 1, 2, 4, 2, 3, 4, 3, 2, 0, 0, 1, 2, 4, 3, 2, 0,
  47. 2, 1, 0, 1, 0, 2, 3, 4, 3, 2, 1, 1, 2, 0, 0, 1,
  48. 1, 2, 3, 4, 4, 3, 2, 1, 2, 3, 4, 4, 2, 1, 0, 1,
  49. 0, 0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2,
  50. };
  51. static char strobe[] = {
  52. 64, 64, 64, 48, 36, 27, 20, 15, 11, 9, 6, 5, 4, 3, 2, 2,
  53. 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  54. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  55. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  56. };
  57. static int GetWaveValue( int nWave, long time, int freq, int amplitude )
  58. {
  59. switch (nWave)
  60. {
  61. case kWaveNone:
  62. return amplitude;
  63. case kWaveSquare:
  64. return ((time * freq >> 11) & 1) * amplitude;
  65. case kWaveSaw:
  66. return abs(0x80 - ((time * freq >> 4) & 0xFF)) * amplitude >> 7;
  67. case kWaveRampup:
  68. return ((time * freq >> 4) & 0xFF) * amplitude >> 8;
  69. case kWaveRampdown:
  70. return (0xFF - ((time * freq >> 4) & 0xFF)) * amplitude >> 8;
  71. case kWaveSine:
  72. return (amplitude + mulscale30(amplitude, Sin(time * freq >> 1))) >> 1;
  73. case kWaveFlicker1:
  74. return flicker1[(time * freq >> 6) & 0x3F] * amplitude;
  75. case kWaveFlicker2:
  76. return flicker2[(time * freq >> 6) & 0x3F] * amplitude >> 2;
  77. case kWaveFlicker3:
  78. return flicker3[(time * freq >> 6) & 0x3F] * amplitude >> 2;
  79. case kWaveFlicker4:
  80. return flicker4[(time * freq >> 6) & 0x3F] * amplitude >> 2;
  81. case kWaveStrobe:
  82. return strobe[(time * freq >> 6) & 0x3F] * amplitude >> 6;
  83. case kWaveSearch:
  84. {
  85. int phi = ((time * freq >> 1) & kAngleMask) << 2;
  86. if (phi > kAngle360)
  87. return 0;
  88. return (amplitude - mulscale30(amplitude, Cos(phi))) >> 1;
  89. }
  90. }
  91. return 0;
  92. };
  93. void DoSectorLighting( void )
  94. {
  95. int i, nXSector, nSector;
  96. int nWave, freq, amplitude, value;
  97. int nWall, startwall, endwall;
  98. for (i = 0; i < shadeCount; i++)
  99. {
  100. nXSector = shadeList[i];
  101. XSECTOR *pXSector = &xsector[nXSector];
  102. nSector = pXSector->reference;
  103. dassert(sector[nSector].extra == nXSector);
  104. // undo previous lighting
  105. if ( pXSector->shade != 0 )
  106. {
  107. value = pXSector->shade;
  108. if ( pXSector->shadeFloor )
  109. sector[nSector].floorshade = (schar)(sector[nSector].floorshade - value);
  110. if ( pXSector->shadeCeiling )
  111. sector[nSector].ceilingshade = (schar)(sector[nSector].ceilingshade - value);
  112. if ( pXSector->shadeWalls )
  113. {
  114. startwall = sector[nSector].wallptr;
  115. endwall = startwall + sector[nSector].wallnum-1;
  116. for (nWall = startwall; nWall <= endwall; nWall++)
  117. wall[nWall].shade = (schar)(wall[nWall].shade - value);
  118. }
  119. pXSector->shade = 0;
  120. }
  121. if ( pXSector->shadeAlways || pXSector->busy )
  122. {
  123. freq = pXSector->freq;
  124. nWave = pXSector->wave;
  125. amplitude = pXSector->amplitude;
  126. if ( !pXSector->shadeAlways && pXSector->busy )
  127. amplitude = mulscale16(amplitude, pXSector->busy);
  128. value = GetWaveValue(nWave, gFrameClock + pXSector->phase, freq, amplitude);
  129. if ( pXSector->shadeFloor )
  130. sector[nSector].floorshade = (schar)ClipRange(sector[nSector].floorshade + value, -128, 127);
  131. if ( pXSector->shadeCeiling )
  132. sector[nSector].ceilingshade = (schar)ClipRange(sector[nSector].ceilingshade + value, -128, 127);
  133. if ( pXSector->shadeWalls )
  134. {
  135. startwall = sector[nSector].wallptr;
  136. endwall = startwall + sector[nSector].wallnum-1;
  137. for (nWall = startwall; nWall <= endwall; nWall++)
  138. wall[nWall].shade = (schar)ClipRange(wall[nWall].shade + value, -128, 127);
  139. }
  140. pXSector->shade = value;
  141. }
  142. }
  143. }
  144. void UndoSectorLighting( void ) // should be used only in mapedit
  145. {
  146. int nXSector, nSector;
  147. int value;
  148. int nWall, startwall, endwall;
  149. for (nSector = 0; nSector < numsectors; nSector++)
  150. {
  151. nXSector = sector[nSector].extra;
  152. if (nXSector <= 0)
  153. continue;
  154. XSECTOR *pXSector = &xsector[nXSector];
  155. if ( pXSector->shade != 0 )
  156. {
  157. value = pXSector->shade;
  158. if ( pXSector->shadeFloor )
  159. sector[nSector].floorshade = (schar)(sector[nSector].floorshade - value);
  160. if ( pXSector->shadeCeiling )
  161. sector[nSector].ceilingshade = (schar)(sector[nSector].ceilingshade - value);
  162. if ( pXSector->shadeWalls )
  163. {
  164. startwall = sector[nSector].wallptr;
  165. endwall = startwall + sector[nSector].wallnum-1;
  166. for (nWall = startwall; nWall <= endwall; nWall++)
  167. wall[nWall].shade = (schar)(wall[nWall].shade - value);
  168. }
  169. pXSector->shade = 0;
  170. }
  171. }
  172. }
  173. void DoSectorPanning( void )
  174. {
  175. int i;
  176. for (i = 0; i < panCount; i++)
  177. {
  178. int nXSector = panList[i];
  179. XSECTOR *pXSector = &xsector[nXSector];
  180. int nSector = pXSector->reference;
  181. dassert(nSector >= 0 && nSector < kMaxSectors);
  182. SECTOR *pSector = &sector[nSector];
  183. dassert(pSector->extra == nXSector);
  184. if ( pXSector->panAlways || pXSector->busy )
  185. {
  186. int panAngle = (pXSector->panAngle - kAngle90) & kAngleMask;
  187. int panVel = pXSector->panVel << kPanScale;
  188. if ( !pXSector->panAlways && (pXSector->busy & kFluxMask) )
  189. panVel = mulscale16(panVel, pXSector->busy);
  190. if ( pXSector->panFloor )
  191. {
  192. int nTile = pSector->floorpicnum;
  193. int panX = (pSector->floorxpanning << 8) + pXSector->floorxpanFrac;
  194. int panY = (pSector->floorypanning << 8) + pXSector->floorypanFrac;
  195. panX += mulscale30(kFrameTicks * panVel, Cos(panAngle)) >>
  196. ((picsiz[nTile] & 0xF) - (pSector->floorstat & kSectorExpand ? 1 : 0));
  197. panY += mulscale30(kFrameTicks * panVel, Sin(panAngle)) >>
  198. ((picsiz[nTile] / 16) - (pSector->floorstat & kSectorExpand ? 1 : 0));
  199. pSector->floorxpanning = (char)(panX >> 8);
  200. pSector->floorypanning = (char)(panY >> 8);
  201. pXSector->floorxpanFrac = panX & 0xFF;
  202. pXSector->floorypanFrac = panY & 0xFF;
  203. }
  204. if ( pXSector->panCeiling )
  205. {
  206. int nTile = pSector->ceilingpicnum;
  207. int panX = (pSector->ceilingxpanning << 8) + pXSector->ceilxpanFrac;
  208. int panY = (pSector->ceilingypanning << 8) + pXSector->ceilypanFrac;
  209. panX += mulscale30(kFrameTicks * panVel, Cos(panAngle)) >>
  210. ((picsiz[nTile] & 0xF) - (pSector->ceilingstat & kSectorExpand ? 1 : 0));
  211. panY += mulscale30(kFrameTicks * panVel, Sin(panAngle)) >>
  212. ((picsiz[nTile] / 16) - (pSector->ceilingstat & kSectorExpand ? 1 : 0));
  213. pSector->ceilingxpanning = (char)(panX >> 8);
  214. pSector->ceilingypanning = (char)(panY >> 8);
  215. pXSector->ceilxpanFrac = panX & 0xFF;
  216. pXSector->ceilypanFrac = panY & 0xFF;
  217. }
  218. }
  219. }
  220. for (i = 0; i < wallPanCount; i++)
  221. {
  222. int nXWall = wallPanList[i];
  223. XWALL *pXWall = &xwall[nXWall];
  224. int nWall = pXWall->reference;
  225. dassert(wall[nWall].extra == nXWall);
  226. if ( pXWall->panAlways || pXWall->busy )
  227. {
  228. int panXVel = pXWall->panXVel << 8;
  229. int panYVel = pXWall->panYVel << 8;
  230. if ( !pXWall->panAlways && (pXWall->busy & kFluxMask) )
  231. {
  232. panXVel = mulscale16(panXVel, pXWall->busy);
  233. panYVel = mulscale16(panYVel, pXWall->busy);
  234. }
  235. int nTile = wall[nWall].picnum;
  236. int panX = (wall[nWall].xpanning << 8) + pXWall->xpanFrac;
  237. int panY = (wall[nWall].ypanning << 8) + pXWall->ypanFrac;
  238. panX += kFrameTicks * panXVel >> (picsiz[nTile] & 0xF);
  239. panY += kFrameTicks * panYVel >> (picsiz[nTile] / 16);
  240. wall[nWall].xpanning = (char)(panX >> 8);
  241. wall[nWall].ypanning = (char)(panY >> 8);
  242. pXWall->xpanFrac = panX & 0xFF;
  243. pXWall->ypanFrac = panY & 0xFF;
  244. }
  245. }
  246. }
  247. void InitSectorFX( void )
  248. {
  249. int i;
  250. shadeCount = 0;
  251. panCount = 0;
  252. wallPanCount = 0;
  253. for (i = 0; i < numsectors; i++)
  254. {
  255. short nXSector = sector[i].extra;
  256. if ( nXSector > 0 )
  257. {
  258. XSECTOR *pXSector = &xsector[nXSector];
  259. if ( pXSector->amplitude != 0 )
  260. shadeList[shadeCount++] = nXSector;
  261. if ( pXSector->panVel != 0 )
  262. panList[panCount++] = nXSector;
  263. }
  264. }
  265. for (i = 0; i < numwalls; i++)
  266. {
  267. short nXWall = wall[i].extra;
  268. if ( nXWall > 0 )
  269. {
  270. XWALL *pXWall = &xwall[nXWall];
  271. if ( pXWall->panXVel != 0 || pXWall->panYVel != 0)
  272. wallPanList[wallPanCount++] = nXWall;
  273. }
  274. }
  275. }