p_maputl.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  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 <stdlib.h>
  23. #include "m_bbox.h"
  24. #include "doomdef.h"
  25. #include "p_local.h"
  26. // State.
  27. #include "r_state.h"
  28. //
  29. // P_AproxDistance
  30. // Gives an estimation of distance (not exact)
  31. //
  32. fixed_t
  33. P_AproxDistance
  34. ( fixed_t dx,
  35. fixed_t dy )
  36. {
  37. dx = abs(dx);
  38. dy = abs(dy);
  39. if (dx < dy)
  40. return dx+dy-(dx>>1);
  41. return dx+dy-(dy>>1);
  42. }
  43. //
  44. // P_PointOnLineSide
  45. // Returns 0 or 1
  46. //
  47. int
  48. P_PointOnLineSide
  49. ( fixed_t x,
  50. fixed_t y,
  51. line_t* line )
  52. {
  53. fixed_t dx;
  54. fixed_t dy;
  55. fixed_t left;
  56. fixed_t right;
  57. if (!line->dx)
  58. {
  59. if (x <= line->v1->x)
  60. return line->dy > 0;
  61. return line->dy < 0;
  62. }
  63. if (!line->dy)
  64. {
  65. if (y <= line->v1->y)
  66. return line->dx < 0;
  67. return line->dx > 0;
  68. }
  69. dx = (x - line->v1->x);
  70. dy = (y - line->v1->y);
  71. left = FixedMul ( line->dy>>FRACBITS , dx );
  72. right = FixedMul ( dy , line->dx>>FRACBITS );
  73. if (right < left)
  74. return 0; // front side
  75. return 1; // back side
  76. }
  77. //
  78. // P_BoxOnLineSide
  79. // Considers the line to be infinite
  80. // Returns side 0 or 1, -1 if box crosses the line.
  81. //
  82. int
  83. P_BoxOnLineSide
  84. ( fixed_t* tmbox,
  85. line_t* ld )
  86. {
  87. int p1 = 0;
  88. int p2 = 0;
  89. switch (ld->slopetype)
  90. {
  91. case ST_HORIZONTAL:
  92. p1 = tmbox[BOXTOP] > ld->v1->y;
  93. p2 = tmbox[BOXBOTTOM] > ld->v1->y;
  94. if (ld->dx < 0)
  95. {
  96. p1 ^= 1;
  97. p2 ^= 1;
  98. }
  99. break;
  100. case ST_VERTICAL:
  101. p1 = tmbox[BOXRIGHT] < ld->v1->x;
  102. p2 = tmbox[BOXLEFT] < ld->v1->x;
  103. if (ld->dy < 0)
  104. {
  105. p1 ^= 1;
  106. p2 ^= 1;
  107. }
  108. break;
  109. case ST_POSITIVE:
  110. p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld);
  111. p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld);
  112. break;
  113. case ST_NEGATIVE:
  114. p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld);
  115. p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld);
  116. break;
  117. }
  118. if (p1 == p2)
  119. return p1;
  120. return -1;
  121. }
  122. //
  123. // P_PointOnDivlineSide
  124. // Returns 0 or 1.
  125. //
  126. int
  127. P_PointOnDivlineSide
  128. ( fixed_t x,
  129. fixed_t y,
  130. divline_t* line )
  131. {
  132. fixed_t dx;
  133. fixed_t dy;
  134. fixed_t left;
  135. fixed_t right;
  136. if (!line->dx)
  137. {
  138. if (x <= line->x)
  139. return line->dy > 0;
  140. return line->dy < 0;
  141. }
  142. if (!line->dy)
  143. {
  144. if (y <= line->y)
  145. return line->dx < 0;
  146. return line->dx > 0;
  147. }
  148. dx = (x - line->x);
  149. dy = (y - line->y);
  150. // try to quickly decide by looking at sign bits
  151. if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
  152. {
  153. if ( (line->dy ^ dx) & 0x80000000 )
  154. return 1; // (left is negative)
  155. return 0;
  156. }
  157. left = FixedMul ( line->dy>>8, dx>>8 );
  158. right = FixedMul ( dy>>8 , line->dx>>8 );
  159. if (right < left)
  160. return 0; // front side
  161. return 1; // back side
  162. }
  163. //
  164. // P_MakeDivline
  165. //
  166. void
  167. P_MakeDivline
  168. ( line_t* li,
  169. divline_t* dl )
  170. {
  171. dl->x = li->v1->x;
  172. dl->y = li->v1->y;
  173. dl->dx = li->dx;
  174. dl->dy = li->dy;
  175. }
  176. //
  177. // P_InterceptVector
  178. // Returns the fractional intercept point
  179. // along the first divline.
  180. // This is only called by the addthings
  181. // and addlines traversers.
  182. //
  183. fixed_t
  184. P_InterceptVector
  185. ( divline_t* v2,
  186. divline_t* v1 )
  187. {
  188. #if 1
  189. fixed_t frac;
  190. fixed_t num;
  191. fixed_t den;
  192. den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
  193. if (den == 0)
  194. return 0;
  195. // I_Error ("P_InterceptVector: parallel");
  196. num =
  197. FixedMul ( (v1->x - v2->x)>>8 ,v1->dy )
  198. +FixedMul ( (v2->y - v1->y)>>8, v1->dx );
  199. frac = FixedDiv (num , den);
  200. return frac;
  201. #else // UNUSED, float debug.
  202. float frac;
  203. float num;
  204. float den;
  205. float v1x;
  206. float v1y;
  207. float v1dx;
  208. float v1dy;
  209. float v2x;
  210. float v2y;
  211. float v2dx;
  212. float v2dy;
  213. v1x = (float)v1->x/FRACUNIT;
  214. v1y = (float)v1->y/FRACUNIT;
  215. v1dx = (float)v1->dx/FRACUNIT;
  216. v1dy = (float)v1->dy/FRACUNIT;
  217. v2x = (float)v2->x/FRACUNIT;
  218. v2y = (float)v2->y/FRACUNIT;
  219. v2dx = (float)v2->dx/FRACUNIT;
  220. v2dy = (float)v2->dy/FRACUNIT;
  221. den = v1dy*v2dx - v1dx*v2dy;
  222. if (den == 0)
  223. return 0; // parallel
  224. num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;
  225. frac = num / den;
  226. return frac*FRACUNIT;
  227. #endif
  228. }
  229. //
  230. // P_LineOpening
  231. // Sets ::g->opentop and ::g->openbottom to the window
  232. // through a two sided line.
  233. // OPTIMIZE: keep this precalculated
  234. //
  235. void P_LineOpening (line_t* maputil_linedef)
  236. {
  237. sector_t* front;
  238. sector_t* back;
  239. if (maputil_linedef->sidenum[1] == -1)
  240. {
  241. // single sided line
  242. ::g->openrange = 0;
  243. return;
  244. }
  245. front = maputil_linedef->frontsector;
  246. back = maputil_linedef->backsector;
  247. if (front->ceilingheight < back->ceilingheight)
  248. ::g->opentop = front->ceilingheight;
  249. else
  250. ::g->opentop = back->ceilingheight;
  251. if (front->floorheight > back->floorheight)
  252. {
  253. ::g->openbottom = front->floorheight;
  254. ::g->lowfloor = back->floorheight;
  255. }
  256. else
  257. {
  258. ::g->openbottom = back->floorheight;
  259. ::g->lowfloor = front->floorheight;
  260. }
  261. ::g->openrange = ::g->opentop - ::g->openbottom;
  262. }
  263. //
  264. // THING POSITION SETTING
  265. //
  266. //
  267. // P_UnsetThingPosition
  268. // Unlinks a thing from block map and ::g->sectors.
  269. // On each position change, BLOCKMAP and other
  270. // lookups maintaining lists ot things inside
  271. // these structures need to be updated.
  272. //
  273. void P_UnsetThingPosition (mobj_t* thing)
  274. {
  275. int blockx;
  276. int blocky;
  277. if ( ! (thing->flags & MF_NOSECTOR) )
  278. {
  279. // inert things don't need to be in blockmap?
  280. // unlink from subsector
  281. if (thing->snext)
  282. thing->snext->sprev = thing->sprev;
  283. if (thing->sprev)
  284. thing->sprev->snext = thing->snext;
  285. else
  286. thing->subsector->sector->thinglist = thing->snext;
  287. }
  288. if ( ! (thing->flags & MF_NOBLOCKMAP) )
  289. {
  290. // inert things don't need to be in ::g->blockmap
  291. // unlink from block map
  292. if (thing->bnext)
  293. thing->bnext->bprev = thing->bprev;
  294. if (thing->bprev)
  295. thing->bprev->bnext = thing->bnext;
  296. else
  297. {
  298. blockx = (thing->x - ::g->bmaporgx)>>MAPBLOCKSHIFT;
  299. blocky = (thing->y - ::g->bmaporgy)>>MAPBLOCKSHIFT;
  300. if (blockx>=0 && blockx < ::g->bmapwidth
  301. && blocky>=0 && blocky < ::g->bmapheight)
  302. {
  303. ::g->blocklinks[blocky*::g->bmapwidth+blockx] = thing->bnext;
  304. }
  305. }
  306. }
  307. }
  308. //
  309. // P_SetThingPosition
  310. // Links a thing into both a block and a subsector
  311. // based on it's x y.
  312. // Sets thing->subsector properly
  313. //
  314. void
  315. P_SetThingPosition (mobj_t* thing)
  316. {
  317. subsector_t* ss;
  318. sector_t* sec;
  319. int blockx;
  320. int blocky;
  321. mobj_t** link;
  322. // link into subsector
  323. ss = R_PointInSubsector (thing->x,thing->y);
  324. thing->subsector = ss;
  325. if ( ! (thing->flags & MF_NOSECTOR) )
  326. {
  327. // invisible things don't go into the sector links
  328. sec = ss->sector;
  329. thing->sprev = NULL;
  330. thing->snext = sec->thinglist;
  331. if (sec->thinglist)
  332. sec->thinglist->sprev = thing;
  333. sec->thinglist = thing;
  334. }
  335. // link into ::g->blockmap
  336. if ( ! (thing->flags & MF_NOBLOCKMAP) )
  337. {
  338. // inert things don't need to be in ::g->blockmap
  339. blockx = (thing->x - ::g->bmaporgx)>>MAPBLOCKSHIFT;
  340. blocky = (thing->y - ::g->bmaporgy)>>MAPBLOCKSHIFT;
  341. if (blockx>=0
  342. && blockx < ::g->bmapwidth
  343. && blocky>=0
  344. && blocky < ::g->bmapheight)
  345. {
  346. link = &::g->blocklinks[blocky*::g->bmapwidth+blockx];
  347. thing->bprev = NULL;
  348. thing->bnext = *link;
  349. if (*link)
  350. (*link)->bprev = thing;
  351. *link = thing;
  352. }
  353. else
  354. {
  355. // thing is off the map
  356. thing->bnext = thing->bprev = NULL;
  357. }
  358. }
  359. }
  360. //
  361. // BLOCK MAP ITERATORS
  362. // For each line/thing in the given mapblock,
  363. // call the passed PIT_* function.
  364. // If the function returns false,
  365. // exit with false without checking anything else.
  366. //
  367. //
  368. // P_BlockLinesIterator
  369. // The ::g->validcount flags are used to avoid checking ::g->lines
  370. // that are marked in multiple mapblocks,
  371. // so increment ::g->validcount before the first call
  372. // to P_BlockLinesIterator, then make one or more calls
  373. // to it.
  374. //
  375. qboolean
  376. P_BlockLinesIterator
  377. ( int x,
  378. int y,
  379. qboolean(*func)(line_t*) )
  380. {
  381. int offset;
  382. short* list;
  383. line_t* ld;
  384. if (x<0
  385. || y<0
  386. || x>=::g->bmapwidth
  387. || y>=::g->bmapheight)
  388. {
  389. return true;
  390. }
  391. offset = y*::g->bmapwidth+x;
  392. offset = *(::g->blockmap+offset);
  393. for ( list = ::g->blockmaplump+offset ; *list != -1 ; list++)
  394. {
  395. ld = &::g->lines[*list];
  396. if (ld->validcount == ::g->validcount)
  397. continue; // line has already been checked
  398. ld->validcount = ::g->validcount;
  399. if ( !func(ld) )
  400. return false;
  401. }
  402. return true; // everything was checked
  403. }
  404. //
  405. // P_BlockThingsIterator
  406. //
  407. qboolean
  408. P_BlockThingsIterator
  409. ( int x,
  410. int y,
  411. qboolean(*func)(mobj_t*) )
  412. {
  413. mobj_t* mobj;
  414. if ( x<0
  415. || y<0
  416. || x>=::g->bmapwidth
  417. || y>=::g->bmapheight)
  418. {
  419. return true;
  420. }
  421. for (mobj = ::g->blocklinks[y*::g->bmapwidth+x] ;
  422. mobj ;
  423. mobj = mobj->bnext)
  424. {
  425. if (!func( mobj ) )
  426. return false;
  427. }
  428. return true;
  429. }
  430. //
  431. // INTERCEPT ROUTINES
  432. //
  433. //
  434. // PIT_AddLineIntercepts.
  435. // Looks for ::g->lines in the given block
  436. // that intercept the given ::g->trace
  437. // to add to the ::g->intercepts list.
  438. //
  439. // A line is crossed if its endpoints
  440. // are on opposite ::g->sides of the ::g->trace.
  441. // Returns true if ::g->earlyout and a solid line hit.
  442. //
  443. qboolean
  444. PIT_AddLineIntercepts (line_t* ld)
  445. {
  446. int s1;
  447. int s2;
  448. fixed_t frac;
  449. divline_t dl;
  450. // avoid precision problems with two routines
  451. if ( ::g->trace.dx > FRACUNIT*16
  452. || ::g->trace.dy > FRACUNIT*16
  453. || ::g->trace.dx < -FRACUNIT*16
  454. || ::g->trace.dy < -FRACUNIT*16)
  455. {
  456. s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &::g->trace);
  457. s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &::g->trace);
  458. }
  459. else
  460. {
  461. s1 = P_PointOnLineSide (::g->trace.x, ::g->trace.y, ld);
  462. s2 = P_PointOnLineSide (::g->trace.x+::g->trace.dx, ::g->trace.y+::g->trace.dy, ld);
  463. }
  464. if (s1 == s2)
  465. return true; // line isn't crossed
  466. // hit the line
  467. P_MakeDivline (ld, &dl);
  468. frac = P_InterceptVector (&::g->trace, &dl);
  469. if (frac < 0)
  470. return true; // behind source
  471. // try to early out the check
  472. if (::g->earlyout
  473. && frac < FRACUNIT
  474. && !ld->backsector)
  475. {
  476. return false; // stop checking
  477. }
  478. ::g->intercept_p->frac = frac;
  479. ::g->intercept_p->isaline = true;
  480. ::g->intercept_p->d.line = ld;
  481. ::g->intercept_p++;
  482. return true; // continue
  483. }
  484. //
  485. // PIT_AddThingIntercepts
  486. //
  487. qboolean PIT_AddThingIntercepts (mobj_t* thing)
  488. {
  489. fixed_t x1;
  490. fixed_t y1;
  491. fixed_t x2;
  492. fixed_t y2;
  493. int s1;
  494. int s2;
  495. qboolean tracepositive;
  496. divline_t dl;
  497. fixed_t frac;
  498. tracepositive = (::g->trace.dx ^ ::g->trace.dy)>0;
  499. // check a corner to corner crossection for hit
  500. if (tracepositive)
  501. {
  502. x1 = thing->x - thing->radius;
  503. y1 = thing->y + thing->radius;
  504. x2 = thing->x + thing->radius;
  505. y2 = thing->y - thing->radius;
  506. }
  507. else
  508. {
  509. x1 = thing->x - thing->radius;
  510. y1 = thing->y - thing->radius;
  511. x2 = thing->x + thing->radius;
  512. y2 = thing->y + thing->radius;
  513. }
  514. s1 = P_PointOnDivlineSide (x1, y1, &::g->trace);
  515. s2 = P_PointOnDivlineSide (x2, y2, &::g->trace);
  516. if (s1 == s2)
  517. return true; // line isn't crossed
  518. dl.x = x1;
  519. dl.y = y1;
  520. dl.dx = x2-x1;
  521. dl.dy = y2-y1;
  522. frac = P_InterceptVector (&::g->trace, &dl);
  523. if (frac < 0)
  524. return true; // behind source
  525. ::g->intercept_p->frac = frac;
  526. ::g->intercept_p->isaline = false;
  527. ::g->intercept_p->d.thing = thing;
  528. ::g->intercept_p++;
  529. return true; // keep going
  530. }
  531. //
  532. // P_TraverseIntercepts
  533. // Returns true if the traverser function returns true
  534. // for all ::g->lines.
  535. //
  536. qboolean
  537. P_TraverseIntercepts
  538. ( traverser_t func,
  539. fixed_t maxfrac )
  540. {
  541. int count;
  542. fixed_t dist;
  543. intercept_t* scan;
  544. intercept_t* in;
  545. count = ::g->intercept_p - ::g->intercepts;
  546. in = 0; // shut up compiler warning
  547. while (count--)
  548. {
  549. dist = MAXINT;
  550. for (scan = ::g->intercepts ; scan < ::g->intercept_p ; scan++)
  551. {
  552. if (scan->frac < dist)
  553. {
  554. dist = scan->frac;
  555. in = scan;
  556. }
  557. }
  558. if (dist > maxfrac)
  559. return true; // checked everything in range
  560. #if 0 // UNUSED
  561. {
  562. // don't check these yet, there may be others inserted
  563. in = scan = ::g->intercepts;
  564. for ( scan = ::g->intercepts ; scan<::g->intercept_p ; scan++)
  565. if (scan->frac > maxfrac)
  566. *in++ = *scan;
  567. ::g->intercept_p = in;
  568. return false;
  569. }
  570. #endif
  571. if ( !func (in) )
  572. return false; // don't bother going farther
  573. in->frac = MAXINT;
  574. }
  575. return true; // everything was traversed
  576. }
  577. //
  578. // P_PathTraverse
  579. // Traces a line from x1,y1 to x2,y2,
  580. // calling the traverser function for each.
  581. // Returns true if the traverser function returns true
  582. // for all ::g->lines.
  583. //
  584. qboolean
  585. P_PathTraverse
  586. ( fixed_t x1,
  587. fixed_t y1,
  588. fixed_t x2,
  589. fixed_t y2,
  590. int flags,
  591. qboolean (*trav) (intercept_t *))
  592. {
  593. fixed_t xt1;
  594. fixed_t yt1;
  595. fixed_t xt2;
  596. fixed_t yt2;
  597. fixed_t xstep;
  598. fixed_t ystep;
  599. fixed_t partial;
  600. fixed_t xintercept;
  601. fixed_t yintercept;
  602. int mapx;
  603. int mapy;
  604. int mapxstep;
  605. int mapystep;
  606. int count;
  607. ::g->earlyout = flags & PT_EARLYOUT;
  608. ::g->validcount++;
  609. ::g->intercept_p = ::g->intercepts;
  610. if ( ((x1-::g->bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
  611. x1 += FRACUNIT; // don't side exactly on a line
  612. if ( ((y1-::g->bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
  613. y1 += FRACUNIT; // don't side exactly on a line
  614. ::g->trace.x = x1;
  615. ::g->trace.y = y1;
  616. ::g->trace.dx = x2 - x1;
  617. ::g->trace.dy = y2 - y1;
  618. x1 -= ::g->bmaporgx;
  619. y1 -= ::g->bmaporgy;
  620. xt1 = x1>>MAPBLOCKSHIFT;
  621. yt1 = y1>>MAPBLOCKSHIFT;
  622. x2 -= ::g->bmaporgx;
  623. y2 -= ::g->bmaporgy;
  624. xt2 = x2>>MAPBLOCKSHIFT;
  625. yt2 = y2>>MAPBLOCKSHIFT;
  626. if (xt2 > xt1)
  627. {
  628. mapxstep = 1;
  629. partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
  630. ystep = FixedDiv (y2-y1,abs(x2-x1));
  631. }
  632. else if (xt2 < xt1)
  633. {
  634. mapxstep = -1;
  635. partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
  636. ystep = FixedDiv (y2-y1,abs(x2-x1));
  637. }
  638. else
  639. {
  640. mapxstep = 0;
  641. partial = FRACUNIT;
  642. ystep = 256*FRACUNIT;
  643. }
  644. yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep);
  645. if (yt2 > yt1)
  646. {
  647. mapystep = 1;
  648. partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
  649. xstep = FixedDiv (x2-x1,abs(y2-y1));
  650. }
  651. else if (yt2 < yt1)
  652. {
  653. mapystep = -1;
  654. partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
  655. xstep = FixedDiv (x2-x1,abs(y2-y1));
  656. }
  657. else
  658. {
  659. mapystep = 0;
  660. partial = FRACUNIT;
  661. xstep = 256*FRACUNIT;
  662. }
  663. xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
  664. // Step through map blocks.
  665. // Count is present to prevent a round off error
  666. // from skipping the break.
  667. mapx = xt1;
  668. mapy = yt1;
  669. for (count = 0 ; count < 64 ; count++)
  670. {
  671. if (flags & PT_ADDLINES)
  672. {
  673. if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts))
  674. return false; // early out
  675. }
  676. if (flags & PT_ADDTHINGS)
  677. {
  678. if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts))
  679. return false; // early out
  680. }
  681. if (mapx == xt2
  682. && mapy == yt2)
  683. {
  684. break;
  685. }
  686. if ( (yintercept >> FRACBITS) == mapy)
  687. {
  688. yintercept += ystep;
  689. mapx += mapxstep;
  690. }
  691. else if ( (xintercept >> FRACBITS) == mapx)
  692. {
  693. xintercept += xstep;
  694. mapy += mapystep;
  695. }
  696. }
  697. // go through the sorted list
  698. return P_TraverseIntercepts ( trav, FRACUNIT );
  699. }