p_sight.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:7k
源码类别:

射击游戏

开发平台:

Visual C++

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // LineOfSight/Visibility checks, uses REJECT Lookup Table.
  21. //
  22. //-----------------------------------------------------------------------------
  23. static const char
  24. rcsid[] = "$Id: p_sight.c,v 1.3 1997/01/28 22:08:28 b1 Exp $";
  25. #include "doomdef.h"
  26. #include "i_system.h"
  27. #include "p_local.h"
  28. // State.
  29. #include "r_state.h"
  30. //
  31. // P_CheckSight
  32. //
  33. fixed_t sightzstart; // eye z of looker
  34. fixed_t topslope;
  35. fixed_t bottomslope; // slopes to top and bottom of target
  36. divline_t strace; // from t1 to t2
  37. fixed_t t2x;
  38. fixed_t t2y;
  39. int sightcounts[2];
  40. //
  41. // P_DivlineSide
  42. // Returns side 0 (front), 1 (back), or 2 (on).
  43. //
  44. int
  45. P_DivlineSide
  46. ( fixed_t x,
  47.   fixed_t y,
  48.   divline_t* node )
  49. {
  50.     fixed_t dx;
  51.     fixed_t dy;
  52.     fixed_t left;
  53.     fixed_t right;
  54.     if (!node->dx)
  55.     {
  56. if (x==node->x)
  57.     return 2;
  58. if (x <= node->x)
  59.     return node->dy > 0;
  60. return node->dy < 0;
  61.     }
  62.     
  63.     if (!node->dy)
  64.     {
  65. if (x==node->y)
  66.     return 2;
  67. if (y <= node->y)
  68.     return node->dx < 0;
  69. return node->dx > 0;
  70.     }
  71.     dx = (x - node->x);
  72.     dy = (y - node->y);
  73.     left =  (node->dy>>FRACBITS) * (dx>>FRACBITS);
  74.     right = (dy>>FRACBITS) * (node->dx>>FRACBITS);
  75.     if (right < left)
  76. return 0; // front side
  77.     
  78.     if (left == right)
  79. return 2;
  80.     return 1; // back side
  81. }
  82. //
  83. // P_InterceptVector2
  84. // Returns the fractional intercept point
  85. // along the first divline.
  86. // This is only called by the addthings and addlines traversers.
  87. //
  88. fixed_t
  89. P_InterceptVector2
  90. ( divline_t* v2,
  91.   divline_t* v1 )
  92. {
  93.     fixed_t frac;
  94.     fixed_t num;
  95.     fixed_t den;
  96.     den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
  97.     if (den == 0)
  98. return 0;
  99.     // I_Error ("P_InterceptVector: parallel");
  100.     
  101.     num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + 
  102. FixedMul ( (v2->y - v1->y)>>8 , v1->dx);
  103.     frac = FixedDiv (num , den);
  104.     return frac;
  105. }
  106. //
  107. // P_CrossSubsector
  108. // Returns true
  109. //  if strace crosses the given subsector successfully.
  110. //
  111. boolean P_CrossSubsector (int num)
  112. {
  113.     seg_t* seg;
  114.     line_t* line;
  115.     int s1;
  116.     int s2;
  117.     int count;
  118.     subsector_t* sub;
  119.     sector_t* front;
  120.     sector_t* back;
  121.     fixed_t opentop;
  122.     fixed_t openbottom;
  123.     divline_t divl;
  124.     vertex_t* v1;
  125.     vertex_t* v2;
  126.     fixed_t frac;
  127.     fixed_t slope;
  128. #ifdef RANGECHECK
  129.     if (num>=numsubsectors)
  130. I_Error ("P_CrossSubsector: ss %i with numss = %i",
  131.  num,
  132.  numsubsectors);
  133. #endif
  134.     sub = &subsectors[num];
  135.     
  136.     // check lines
  137.     count = sub->numlines;
  138.     seg = &segs[sub->firstline];
  139.     for ( ; count ; seg++, count--)
  140.     {
  141. line = seg->linedef;
  142. // allready checked other side?
  143. if (line->validcount == validcount)
  144.     continue;
  145. line->validcount = validcount;
  146. v1 = line->v1;
  147. v2 = line->v2;
  148. s1 = P_DivlineSide (v1->x,v1->y, &strace);
  149. s2 = P_DivlineSide (v2->x, v2->y, &strace);
  150. // line isn't crossed?
  151. if (s1 == s2)
  152.     continue;
  153. divl.x = v1->x;
  154. divl.y = v1->y;
  155. divl.dx = v2->x - v1->x;
  156. divl.dy = v2->y - v1->y;
  157. s1 = P_DivlineSide (strace.x, strace.y, &divl);
  158. s2 = P_DivlineSide (t2x, t2y, &divl);
  159. // line isn't crossed?
  160. if (s1 == s2)
  161.     continue;
  162. // stop because it is not two sided anyway
  163. // might do this after updating validcount?
  164. if ( !(line->flags & ML_TWOSIDED) )
  165.     return false;
  166. // crosses a two sided line
  167. front = seg->frontsector;
  168. back = seg->backsector;
  169. // no wall to block sight with?
  170. if (front->floorheight == back->floorheight
  171.     && front->ceilingheight == back->ceilingheight)
  172.     continue;
  173. // possible occluder
  174. // because of ceiling height differences
  175. if (front->ceilingheight < back->ceilingheight)
  176.     opentop = front->ceilingheight;
  177. else
  178.     opentop = back->ceilingheight;
  179. // because of ceiling height differences
  180. if (front->floorheight > back->floorheight)
  181.     openbottom = front->floorheight;
  182. else
  183.     openbottom = back->floorheight;
  184. // quick test for totally closed doors
  185. if (openbottom >= opentop)
  186.     return false; // stop
  187. frac = P_InterceptVector2 (&strace, &divl);
  188. if (front->floorheight != back->floorheight)
  189. {
  190.     slope = FixedDiv (openbottom - sightzstart , frac);
  191.     if (slope > bottomslope)
  192. bottomslope = slope;
  193. }
  194. if (front->ceilingheight != back->ceilingheight)
  195. {
  196.     slope = FixedDiv (opentop - sightzstart , frac);
  197.     if (slope < topslope)
  198. topslope = slope;
  199. }
  200. if (topslope <= bottomslope)
  201.     return false; // stop
  202.     }
  203.     // passed the subsector ok
  204.     return true;
  205. }
  206. //
  207. // P_CrossBSPNode
  208. // Returns true
  209. //  if strace crosses the given node successfully.
  210. //
  211. boolean P_CrossBSPNode (int bspnum)
  212. {
  213.     node_t* bsp;
  214.     int side;
  215.     if (bspnum & NF_SUBSECTOR)
  216.     {
  217. if (bspnum == -1)
  218.     return P_CrossSubsector (0);
  219. else
  220.     return P_CrossSubsector (bspnum&(~NF_SUBSECTOR));
  221.     }
  222.     bsp = &nodes[bspnum];
  223.     
  224.     // decide which side the start point is on
  225.     side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp);
  226.     if (side == 2)
  227. side = 0; // an "on" should cross both sides
  228.     // cross the starting side
  229.     if (!P_CrossBSPNode (bsp->children[side]) )
  230. return false;
  231.     // the partition plane is crossed here
  232.     if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp))
  233.     {
  234. // the line doesn't touch the other side
  235. return true;
  236.     }
  237.     
  238.     // cross the ending side
  239.     return P_CrossBSPNode (bsp->children[side^1]);
  240. }
  241. //
  242. // P_CheckSight
  243. // Returns true
  244. //  if a straight line between t1 and t2 is unobstructed.
  245. // Uses REJECT.
  246. //
  247. boolean
  248. P_CheckSight
  249. ( mobj_t* t1,
  250.   mobj_t* t2 )
  251. {
  252.     int s1;
  253.     int s2;
  254.     int pnum;
  255.     int bytenum;
  256.     int bitnum;
  257.     
  258.     // First check for trivial rejection.
  259.     // Determine subsector entries in REJECT table.
  260.     s1 = (t1->subsector->sector - sectors);
  261.     s2 = (t2->subsector->sector - sectors);
  262.     pnum = s1*numsectors + s2;
  263.     bytenum = pnum>>3;
  264.     bitnum = 1 << (pnum&7);
  265.     // Check in REJECT table.
  266.     if (rejectmatrix[bytenum]&bitnum)
  267.     {
  268. sightcounts[0]++;
  269. // can't possibly be connected
  270. return false;
  271.     }
  272.     // An unobstructed LOS is possible.
  273.     // Now look from eyes of t1 to any part of t2.
  274.     sightcounts[1]++;
  275.     validcount++;
  276.     sightzstart = t1->z + t1->height - (t1->height>>2);
  277.     topslope = (t2->z+t2->height) - sightzstart;
  278.     bottomslope = (t2->z) - sightzstart;
  279.     strace.x = t1->x;
  280.     strace.y = t1->y;
  281.     t2x = t2->x;
  282.     t2y = t2->y;
  283.     strace.dx = t2->x - t1->x;
  284.     strace.dy = t2->y - t1->y;
  285.     // the head node is the last node output
  286.     return P_CrossBSPNode (numnodes-1);
  287. }