p_sight.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include "doomdef.h"
  23. #include "i_system.h"
  24. #include "p_local.h"
  25. // State.
  26. #include "r_state.h"
  27. //
  28. // P_CheckSight
  29. //
  30. //
  31. // P_DivlineSide
  32. // Returns side 0 (front), 1 (back), or 2 (on).
  33. //
  34. int
  35. P_DivlineSide
  36. ( fixed_t x,
  37. fixed_t y,
  38. divline_t* node )
  39. {
  40. fixed_t dx;
  41. fixed_t dy;
  42. fixed_t left;
  43. fixed_t right;
  44. if (!node->dx)
  45. {
  46. if (x==node->x)
  47. return 2;
  48. if (x <= node->x)
  49. return node->dy > 0;
  50. return node->dy < 0;
  51. }
  52. if (!node->dy)
  53. {
  54. if (x==node->y)
  55. return 2;
  56. if (y <= node->y)
  57. return node->dx < 0;
  58. return node->dx > 0;
  59. }
  60. dx = (x - node->x);
  61. dy = (y - node->y);
  62. left = (node->dy>>FRACBITS) * (dx>>FRACBITS);
  63. right = (dy>>FRACBITS) * (node->dx>>FRACBITS);
  64. if (right < left)
  65. return 0; // front side
  66. if (left == right)
  67. return 2;
  68. return 1; // back side
  69. }
  70. //
  71. // P_InterceptVector2
  72. // Returns the fractional intercept point
  73. // along the first divline.
  74. // This is only called by the addthings and addlines traversers.
  75. //
  76. fixed_t
  77. P_InterceptVector2
  78. ( divline_t* v2,
  79. divline_t* v1 )
  80. {
  81. fixed_t frac;
  82. fixed_t num;
  83. fixed_t den;
  84. den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
  85. if (den == 0)
  86. return 0;
  87. // I_Error ("P_InterceptVector: parallel");
  88. num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) +
  89. FixedMul ( (v2->y - v1->y)>>8 , v1->dx);
  90. frac = FixedDiv (num , den);
  91. return frac;
  92. }
  93. //
  94. // P_CrossSubsector
  95. // Returns true
  96. // if ::g->strace crosses the given subsector successfully.
  97. //
  98. qboolean P_CrossSubsector (int num)
  99. {
  100. seg_t* seg;
  101. line_t* line;
  102. int s1;
  103. int s2;
  104. int count;
  105. subsector_t* sub;
  106. sector_t* front;
  107. sector_t* back;
  108. fixed_t psight_opentop;
  109. fixed_t psight_openbottom;
  110. divline_t divl;
  111. vertex_t* v1;
  112. vertex_t* v2;
  113. fixed_t frac;
  114. fixed_t slope;
  115. #ifdef RANGECHECK
  116. if (num>=::g->numsubsectors)
  117. I_Error ("P_CrossSubsector: ss %i with numss = %i",
  118. num,
  119. ::g->numsubsectors);
  120. #endif
  121. sub = &::g->subsectors[num];
  122. // check ::g->lines
  123. count = sub->numlines;
  124. seg = &::g->segs[sub->firstline];
  125. for ( ; count ; seg++, count--)
  126. {
  127. line = seg->linedef;
  128. // allready checked other side?
  129. if (line->validcount == ::g->validcount)
  130. continue;
  131. line->validcount = ::g->validcount;
  132. v1 = line->v1;
  133. v2 = line->v2;
  134. s1 = P_DivlineSide (v1->x,v1->y, &::g->strace);
  135. s2 = P_DivlineSide (v2->x, v2->y, &::g->strace);
  136. // line isn't crossed?
  137. if (s1 == s2)
  138. continue;
  139. divl.x = v1->x;
  140. divl.y = v1->y;
  141. divl.dx = v2->x - v1->x;
  142. divl.dy = v2->y - v1->y;
  143. s1 = P_DivlineSide (::g->strace.x, ::g->strace.y, &divl);
  144. s2 = P_DivlineSide (::g->t2x, ::g->t2y, &divl);
  145. // line isn't crossed?
  146. if (s1 == s2)
  147. continue;
  148. // stop because it is not two sided anyway
  149. // might do this after updating validcount?
  150. if ( !(line->flags & ML_TWOSIDED) )
  151. return false;
  152. // crosses a two sided line
  153. front = seg->frontsector;
  154. back = seg->backsector;
  155. // no wall to block sight with?
  156. if (front->floorheight == back->floorheight
  157. && front->ceilingheight == back->ceilingheight)
  158. continue;
  159. // possible occluder
  160. // because of ceiling height differences
  161. if (front->ceilingheight < back->ceilingheight)
  162. psight_opentop = front->ceilingheight;
  163. else
  164. psight_opentop = back->ceilingheight;
  165. // because of ceiling height differences
  166. if (front->floorheight > back->floorheight)
  167. psight_openbottom = front->floorheight;
  168. else
  169. psight_openbottom = back->floorheight;
  170. // quick test for totally closed doors
  171. if (psight_openbottom >= psight_opentop)
  172. return false; // stop
  173. frac = P_InterceptVector2 (&::g->strace, &divl);
  174. if (front->floorheight != back->floorheight)
  175. {
  176. slope = FixedDiv (psight_openbottom - ::g->sightzstart , frac);
  177. if (slope > ::g->bottomslope)
  178. ::g->bottomslope = slope;
  179. }
  180. if (front->ceilingheight != back->ceilingheight)
  181. {
  182. slope = FixedDiv (psight_opentop - ::g->sightzstart , frac);
  183. if (slope < ::g->topslope)
  184. ::g->topslope = slope;
  185. }
  186. if (::g->topslope <= ::g->bottomslope)
  187. return false; // stop
  188. }
  189. // passed the subsector ok
  190. return true;
  191. }
  192. //
  193. // P_CrossBSPNode
  194. // Returns true
  195. // if ::g->strace crosses the given node successfully.
  196. //
  197. qboolean P_CrossBSPNode (int bspnum)
  198. {
  199. node_t* bsp;
  200. int side;
  201. if (bspnum & NF_SUBSECTOR)
  202. {
  203. if (bspnum == -1)
  204. return P_CrossSubsector (0);
  205. else
  206. return P_CrossSubsector (bspnum&(~NF_SUBSECTOR));
  207. }
  208. bsp = &::g->nodes[bspnum];
  209. // decide which side the start point is on
  210. side = P_DivlineSide (::g->strace.x, ::g->strace.y, (divline_t *)bsp);
  211. if (side == 2)
  212. side = 0; // an "on" should cross both ::g->sides
  213. // cross the starting side
  214. if (!P_CrossBSPNode (bsp->children[side]) )
  215. return false;
  216. // the partition plane is crossed here
  217. if (side == P_DivlineSide (::g->t2x, ::g->t2y,(divline_t *)bsp))
  218. {
  219. // the line doesn't touch the other side
  220. return true;
  221. }
  222. // cross the ending side
  223. return P_CrossBSPNode (bsp->children[side^1]);
  224. }
  225. //
  226. // P_CheckSight
  227. // Returns true
  228. // if a straight line between t1 and t2 is unobstructed.
  229. // Uses REJECT.
  230. //
  231. qboolean
  232. P_CheckSight
  233. ( mobj_t* t1,
  234. mobj_t* t2 )
  235. {
  236. int s1;
  237. int s2;
  238. int pnum;
  239. int bytenum;
  240. int bitnum;
  241. // First check for trivial rejection.
  242. // Determine subsector entries in REJECT table.
  243. s1 = (t1->subsector->sector - ::g->sectors);
  244. s2 = (t2->subsector->sector - ::g->sectors);
  245. pnum = s1*::g->numsectors + s2;
  246. bytenum = pnum>>3;
  247. bitnum = 1 << (pnum&7);
  248. // Check in REJECT table.
  249. if (::g->rejectmatrix[bytenum]&bitnum)
  250. {
  251. ::g->sightcounts[0]++;
  252. // can't possibly be connected
  253. return false;
  254. }
  255. // An unobstructed LOS is possible.
  256. // Now look from eyes of t1 to any part of t2.
  257. ::g->sightcounts[1]++;
  258. ::g->validcount++;
  259. ::g->sightzstart = t1->z + t1->height - (t1->height>>2);
  260. ::g->topslope = (t2->z+t2->height) - ::g->sightzstart;
  261. ::g->bottomslope = (t2->z) - ::g->sightzstart;
  262. ::g->strace.x = t1->x;
  263. ::g->strace.y = t1->y;
  264. ::g->t2x = t2->x;
  265. ::g->t2y = t2->y;
  266. ::g->strace.dx = t2->x - t1->x;
  267. ::g->strace.dy = t2->y - t1->y;
  268. // the head node is the last node output
  269. return P_CrossBSPNode (::g->numnodes-1);
  270. }