world.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // world.c -- world query functions
  16. #include "quakedef.h"
  17. /*
  18. entities never clip against themselves, or their owner
  19. line of sight checks trace->crosscontent, but bullets don't
  20. */
  21. typedef struct
  22. {
  23. vec3_t boxmins, boxmaxs;// enclose the test object along entire move
  24. float *mins, *maxs; // size of the moving object
  25. vec3_t mins2, maxs2; // size when clipping against mosnters
  26. float *start, *end;
  27. trace_t trace;
  28. int type;
  29. edict_t *passedict;
  30. } moveclip_t;
  31. int SV_HullPointContents (hull_t *hull, int num, vec3_t p);
  32. /*
  33. ===============================================================================
  34. HULL BOXES
  35. ===============================================================================
  36. */
  37. static hull_t box_hull;
  38. static dclipnode_t box_clipnodes[6];
  39. static mplane_t box_planes[6];
  40. /*
  41. ===================
  42. SV_InitBoxHull
  43. Set up the planes and clipnodes so that the six floats of a bounding box
  44. can just be stored out and get a proper hull_t structure.
  45. ===================
  46. */
  47. void SV_InitBoxHull (void)
  48. {
  49. int i;
  50. int side;
  51. box_hull.clipnodes = box_clipnodes;
  52. box_hull.planes = box_planes;
  53. box_hull.firstclipnode = 0;
  54. box_hull.lastclipnode = 5;
  55. for (i=0 ; i<6 ; i++)
  56. {
  57. box_clipnodes[i].planenum = i;
  58. side = i&1;
  59. box_clipnodes[i].children[side] = CONTENTS_EMPTY;
  60. if (i != 5)
  61. box_clipnodes[i].children[side^1] = i + 1;
  62. else
  63. box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
  64. box_planes[i].type = i>>1;
  65. box_planes[i].normal[i>>1] = 1;
  66. }
  67. }
  68. /*
  69. ===================
  70. SV_HullForBox
  71. To keep everything totally uniform, bounding boxes are turned into small
  72. BSP trees instead of being compared directly.
  73. ===================
  74. */
  75. hull_t *SV_HullForBox (vec3_t mins, vec3_t maxs)
  76. {
  77. box_planes[0].dist = maxs[0];
  78. box_planes[1].dist = mins[0];
  79. box_planes[2].dist = maxs[1];
  80. box_planes[3].dist = mins[1];
  81. box_planes[4].dist = maxs[2];
  82. box_planes[5].dist = mins[2];
  83. return &box_hull;
  84. }
  85. /*
  86. ================
  87. SV_HullForEntity
  88. Returns a hull that can be used for testing or clipping an object of mins/maxs
  89. size.
  90. Offset is filled in to contain the adjustment that must be added to the
  91. testing object's origin to get a point to use with the returned hull.
  92. ================
  93. */
  94. hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset)
  95. {
  96. model_t *model;
  97. vec3_t size;
  98. vec3_t hullmins, hullmaxs;
  99. hull_t *hull;
  100. // decide which clipping hull to use, based on the size
  101. if (ent->v.solid == SOLID_BSP)
  102. { // explicit hulls in the BSP model
  103. if (ent->v.movetype != MOVETYPE_PUSH)
  104. Sys_Error ("SOLID_BSP without MOVETYPE_PUSH");
  105. model = sv.models[ (int)ent->v.modelindex ];
  106. if (!model || model->type != mod_brush)
  107. Sys_Error ("MOVETYPE_PUSH with a non bsp model");
  108. VectorSubtract (maxs, mins, size);
  109. if (size[0] < 3)
  110. hull = &model->hulls[0];
  111. else if (size[0] <= 32)
  112. hull = &model->hulls[1];
  113. else
  114. hull = &model->hulls[2];
  115. // calculate an offset value to center the origin
  116. VectorSubtract (hull->clip_mins, mins, offset);
  117. VectorAdd (offset, ent->v.origin, offset);
  118. }
  119. else
  120. { // create a temp hull from bounding box sizes
  121. VectorSubtract (ent->v.mins, maxs, hullmins);
  122. VectorSubtract (ent->v.maxs, mins, hullmaxs);
  123. hull = SV_HullForBox (hullmins, hullmaxs);
  124. VectorCopy (ent->v.origin, offset);
  125. }
  126. return hull;
  127. }
  128. /*
  129. ===============================================================================
  130. ENTITY AREA CHECKING
  131. ===============================================================================
  132. */
  133. typedef struct areanode_s
  134. {
  135. int axis; // -1 = leaf node
  136. float dist;
  137. struct areanode_s *children[2];
  138. link_t trigger_edicts;
  139. link_t solid_edicts;
  140. } areanode_t;
  141. #define AREA_DEPTH 4
  142. #define AREA_NODES 32
  143. static areanode_t sv_areanodes[AREA_NODES];
  144. static int sv_numareanodes;
  145. /*
  146. ===============
  147. SV_CreateAreaNode
  148. ===============
  149. */
  150. areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs)
  151. {
  152. areanode_t *anode;
  153. vec3_t size;
  154. vec3_t mins1, maxs1, mins2, maxs2;
  155. anode = &sv_areanodes[sv_numareanodes];
  156. sv_numareanodes++;
  157. ClearLink (&anode->trigger_edicts);
  158. ClearLink (&anode->solid_edicts);
  159. if (depth == AREA_DEPTH)
  160. {
  161. anode->axis = -1;
  162. anode->children[0] = anode->children[1] = NULL;
  163. return anode;
  164. }
  165. VectorSubtract (maxs, mins, size);
  166. if (size[0] > size[1])
  167. anode->axis = 0;
  168. else
  169. anode->axis = 1;
  170. anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
  171. VectorCopy (mins, mins1);
  172. VectorCopy (mins, mins2);
  173. VectorCopy (maxs, maxs1);
  174. VectorCopy (maxs, maxs2);
  175. maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
  176. anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
  177. anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
  178. return anode;
  179. }
  180. /*
  181. ===============
  182. SV_ClearWorld
  183. ===============
  184. */
  185. void SV_ClearWorld (void)
  186. {
  187. SV_InitBoxHull ();
  188. memset (sv_areanodes, 0, sizeof(sv_areanodes));
  189. sv_numareanodes = 0;
  190. SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs);
  191. }
  192. /*
  193. ===============
  194. SV_UnlinkEdict
  195. ===============
  196. */
  197. void SV_UnlinkEdict (edict_t *ent)
  198. {
  199. if (!ent->area.prev)
  200. return; // not linked in anywhere
  201. RemoveLink (&ent->area);
  202. ent->area.prev = ent->area.next = NULL;
  203. }
  204. /*
  205. ====================
  206. SV_TouchLinks
  207. ====================
  208. */
  209. void SV_TouchLinks ( edict_t *ent, areanode_t *node )
  210. {
  211. link_t *l, *next;
  212. edict_t *touch;
  213. int old_self, old_other;
  214. // touch linked edicts
  215. for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next)
  216. {
  217. next = l->next;
  218. touch = EDICT_FROM_AREA(l);
  219. if (touch == ent)
  220. continue;
  221. if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER)
  222. continue;
  223. if (ent->v.absmin[0] > touch->v.absmax[0]
  224. || ent->v.absmin[1] > touch->v.absmax[1]
  225. || ent->v.absmin[2] > touch->v.absmax[2]
  226. || ent->v.absmax[0] < touch->v.absmin[0]
  227. || ent->v.absmax[1] < touch->v.absmin[1]
  228. || ent->v.absmax[2] < touch->v.absmin[2] )
  229. continue;
  230. old_self = pr_global_struct->self;
  231. old_other = pr_global_struct->other;
  232. pr_global_struct->self = EDICT_TO_PROG(touch);
  233. pr_global_struct->other = EDICT_TO_PROG(ent);
  234. pr_global_struct->time = sv.time;
  235. PR_ExecuteProgram (touch->v.touch);
  236. pr_global_struct->self = old_self;
  237. pr_global_struct->other = old_other;
  238. }
  239. // recurse down both sides
  240. if (node->axis == -1)
  241. return;
  242. if ( ent->v.absmax[node->axis] > node->dist )
  243. SV_TouchLinks ( ent, node->children[0] );
  244. if ( ent->v.absmin[node->axis] < node->dist )
  245. SV_TouchLinks ( ent, node->children[1] );
  246. }
  247. /*
  248. ===============
  249. SV_FindTouchedLeafs
  250. ===============
  251. */
  252. void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
  253. {
  254. mplane_t *splitplane;
  255. mleaf_t *leaf;
  256. int sides;
  257. int leafnum;
  258. if (node->contents == CONTENTS_SOLID)
  259. return;
  260. // add an efrag if the node is a leaf
  261. if ( node->contents < 0)
  262. {
  263. if (ent->num_leafs == MAX_ENT_LEAFS)
  264. return;
  265. leaf = (mleaf_t *)node;
  266. leafnum = leaf - sv.worldmodel->leafs - 1;
  267. ent->leafnums[ent->num_leafs] = leafnum;
  268. ent->num_leafs++;
  269. return;
  270. }
  271. // NODE_MIXED
  272. splitplane = node->plane;
  273. sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane);
  274. // recurse down the contacted sides
  275. if (sides & 1)
  276. SV_FindTouchedLeafs (ent, node->children[0]);
  277. if (sides & 2)
  278. SV_FindTouchedLeafs (ent, node->children[1]);
  279. }
  280. /*
  281. ===============
  282. SV_LinkEdict
  283. ===============
  284. */
  285. void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
  286. {
  287. areanode_t *node;
  288. if (ent->area.prev)
  289. SV_UnlinkEdict (ent); // unlink from old position
  290. if (ent == sv.edicts)
  291. return; // don't add the world
  292. if (ent->free)
  293. return;
  294. // set the abs box
  295. #ifdef QUAKE2
  296. if (ent->v.solid == SOLID_BSP &&
  297. (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
  298. { // expand for rotation
  299. float max, v;
  300. int i;
  301. max = 0;
  302. for (i=0 ; i<3 ; i++)
  303. {
  304. v =fabs( ent->v.mins[i]);
  305. if (v > max)
  306. max = v;
  307. v =fabs( ent->v.maxs[i]);
  308. if (v > max)
  309. max = v;
  310. }
  311. for (i=0 ; i<3 ; i++)
  312. {
  313. ent->v.absmin[i] = ent->v.origin[i] - max;
  314. ent->v.absmax[i] = ent->v.origin[i] + max;
  315. }
  316. }
  317. else
  318. #endif
  319. {
  320. VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
  321. VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
  322. }
  323. //
  324. // to make items easier to pick up and allow them to be grabbed off
  325. // of shelves, the abs sizes are expanded
  326. //
  327. if ((int)ent->v.flags & FL_ITEM)
  328. {
  329. ent->v.absmin[0] -= 15;
  330. ent->v.absmin[1] -= 15;
  331. ent->v.absmax[0] += 15;
  332. ent->v.absmax[1] += 15;
  333. }
  334. else
  335. { // because movement is clipped an epsilon away from an actual edge,
  336. // we must fully check even when bounding boxes don't quite touch
  337. ent->v.absmin[0] -= 1;
  338. ent->v.absmin[1] -= 1;
  339. ent->v.absmin[2] -= 1;
  340. ent->v.absmax[0] += 1;
  341. ent->v.absmax[1] += 1;
  342. ent->v.absmax[2] += 1;
  343. }
  344. // link to PVS leafs
  345. ent->num_leafs = 0;
  346. if (ent->v.modelindex)
  347. SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
  348. if (ent->v.solid == SOLID_NOT)
  349. return;
  350. // find the first node that the ent's box crosses
  351. node = sv_areanodes;
  352. while (1)
  353. {
  354. if (node->axis == -1)
  355. break;
  356. if (ent->v.absmin[node->axis] > node->dist)
  357. node = node->children[0];
  358. else if (ent->v.absmax[node->axis] < node->dist)
  359. node = node->children[1];
  360. else
  361. break; // crosses the node
  362. }
  363. // link it in
  364. if (ent->v.solid == SOLID_TRIGGER)
  365. InsertLinkBefore (&ent->area, &node->trigger_edicts);
  366. else
  367. InsertLinkBefore (&ent->area, &node->solid_edicts);
  368. // if touch_triggers, touch all entities at this node and decend for more
  369. if (touch_triggers)
  370. SV_TouchLinks ( ent, sv_areanodes );
  371. }
  372. /*
  373. ===============================================================================
  374. POINT TESTING IN HULLS
  375. ===============================================================================
  376. */
  377. #if !id386
  378. /*
  379. ==================
  380. SV_HullPointContents
  381. ==================
  382. */
  383. int SV_HullPointContents (hull_t *hull, int num, vec3_t p)
  384. {
  385. float d;
  386. dclipnode_t *node;
  387. mplane_t *plane;
  388. while (num >= 0)
  389. {
  390. if (num < hull->firstclipnode || num > hull->lastclipnode)
  391. Sys_Error ("SV_HullPointContents: bad node number");
  392. node = hull->clipnodes + num;
  393. plane = hull->planes + node->planenum;
  394. if (plane->type < 3)
  395. d = p[plane->type] - plane->dist;
  396. else
  397. d = DotProduct (plane->normal, p) - plane->dist;
  398. if (d < 0)
  399. num = node->children[1];
  400. else
  401. num = node->children[0];
  402. }
  403. return num;
  404. }
  405. #endif // !id386
  406. /*
  407. ==================
  408. SV_PointContents
  409. ==================
  410. */
  411. int SV_PointContents (vec3_t p)
  412. {
  413. int cont;
  414. cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
  415. if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN)
  416. cont = CONTENTS_WATER;
  417. return cont;
  418. }
  419. int SV_TruePointContents (vec3_t p)
  420. {
  421. return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
  422. }
  423. //===========================================================================
  424. /*
  425. ============
  426. SV_TestEntityPosition
  427. This could be a lot more efficient...
  428. ============
  429. */
  430. edict_t *SV_TestEntityPosition (edict_t *ent)
  431. {
  432. trace_t trace;
  433. trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent);
  434. if (trace.startsolid)
  435. return sv.edicts;
  436. return NULL;
  437. }
  438. /*
  439. ===============================================================================
  440. LINE TESTING IN HULLS
  441. ===============================================================================
  442. */
  443. // 1/32 epsilon to keep floating point happy
  444. #define DIST_EPSILON (0.03125)
  445. /*
  446. ==================
  447. SV_RecursiveHullCheck
  448. ==================
  449. */
  450. qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
  451. {
  452. dclipnode_t *node;
  453. mplane_t *plane;
  454. float t1, t2;
  455. float frac;
  456. int i;
  457. vec3_t mid;
  458. int side;
  459. float midf;
  460. // check for empty
  461. if (num < 0)
  462. {
  463. if (num != CONTENTS_SOLID)
  464. {
  465. trace->allsolid = false;
  466. if (num == CONTENTS_EMPTY)
  467. trace->inopen = true;
  468. else
  469. trace->inwater = true;
  470. }
  471. else
  472. trace->startsolid = true;
  473. return true; // empty
  474. }
  475. if (num < hull->firstclipnode || num > hull->lastclipnode)
  476. Sys_Error ("SV_RecursiveHullCheck: bad node number");
  477. //
  478. // find the point distances
  479. //
  480. node = hull->clipnodes + num;
  481. plane = hull->planes + node->planenum;
  482. if (plane->type < 3)
  483. {
  484. t1 = p1[plane->type] - plane->dist;
  485. t2 = p2[plane->type] - plane->dist;
  486. }
  487. else
  488. {
  489. t1 = DotProduct (plane->normal, p1) - plane->dist;
  490. t2 = DotProduct (plane->normal, p2) - plane->dist;
  491. }
  492. #if 1
  493. if (t1 >= 0 && t2 >= 0)
  494. return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
  495. if (t1 < 0 && t2 < 0)
  496. return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
  497. #else
  498. if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
  499. return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
  500. if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
  501. return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
  502. #endif
  503. // put the crosspoint DIST_EPSILON pixels on the near side
  504. if (t1 < 0)
  505. frac = (t1 + DIST_EPSILON)/(t1-t2);
  506. else
  507. frac = (t1 - DIST_EPSILON)/(t1-t2);
  508. if (frac < 0)
  509. frac = 0;
  510. if (frac > 1)
  511. frac = 1;
  512. midf = p1f + (p2f - p1f)*frac;
  513. for (i=0 ; i<3 ; i++)
  514. mid[i] = p1[i] + frac*(p2[i] - p1[i]);
  515. side = (t1 < 0);
  516. // move up to the node
  517. if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
  518. return false;
  519. #ifdef PARANOID
  520. if (SV_HullPointContents (sv_hullmodel, mid, node->children[side])
  521. == CONTENTS_SOLID)
  522. {
  523. Con_Printf ("mid PointInHullSolid\n");
  524. return false;
  525. }
  526. #endif
  527. if (SV_HullPointContents (hull, node->children[side^1], mid)
  528. != CONTENTS_SOLID)
  529. // go past the node
  530. return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
  531. if (trace->allsolid)
  532. return false; // never got out of the solid area
  533. //==================
  534. // the other side of the node is solid, this is the impact point
  535. //==================
  536. if (!side)
  537. {
  538. VectorCopy (plane->normal, trace->plane.normal);
  539. trace->plane.dist = plane->dist;
  540. }
  541. else
  542. {
  543. VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
  544. trace->plane.dist = -plane->dist;
  545. }
  546. while (SV_HullPointContents (hull, hull->firstclipnode, mid)
  547. == CONTENTS_SOLID)
  548. { // shouldn't really happen, but does occasionally
  549. frac -= 0.1;
  550. if (frac < 0)
  551. {
  552. trace->fraction = midf;
  553. VectorCopy (mid, trace->endpos);
  554. Con_DPrintf ("backup past 0\n");
  555. return false;
  556. }
  557. midf = p1f + (p2f - p1f)*frac;
  558. for (i=0 ; i<3 ; i++)
  559. mid[i] = p1[i] + frac*(p2[i] - p1[i]);
  560. }
  561. trace->fraction = midf;
  562. VectorCopy (mid, trace->endpos);
  563. return false;
  564. }
  565. /*
  566. ==================
  567. SV_ClipMoveToEntity
  568. Handles selection or creation of a clipping hull, and offseting (and
  569. eventually rotation) of the end points
  570. ==================
  571. */
  572. trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
  573. {
  574. trace_t trace;
  575. vec3_t offset;
  576. vec3_t start_l, end_l;
  577. hull_t *hull;
  578. // fill in a default trace
  579. memset (&trace, 0, sizeof(trace_t));
  580. trace.fraction = 1;
  581. trace.allsolid = true;
  582. VectorCopy (end, trace.endpos);
  583. // get the clipping hull
  584. hull = SV_HullForEntity (ent, mins, maxs, offset);
  585. VectorSubtract (start, offset, start_l);
  586. VectorSubtract (end, offset, end_l);
  587. #ifdef QUAKE2
  588. // rotate start and end into the models frame of reference
  589. if (ent->v.solid == SOLID_BSP &&
  590. (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
  591. {
  592. vec3_t a;
  593. vec3_t forward, right, up;
  594. vec3_t temp;
  595. AngleVectors (ent->v.angles, forward, right, up);
  596. VectorCopy (start_l, temp);
  597. start_l[0] = DotProduct (temp, forward);
  598. start_l[1] = -DotProduct (temp, right);
  599. start_l[2] = DotProduct (temp, up);
  600. VectorCopy (end_l, temp);
  601. end_l[0] = DotProduct (temp, forward);
  602. end_l[1] = -DotProduct (temp, right);
  603. end_l[2] = DotProduct (temp, up);
  604. }
  605. #endif
  606. // trace a line through the apropriate clipping hull
  607. SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
  608. #ifdef QUAKE2
  609. // rotate endpos back to world frame of reference
  610. if (ent->v.solid == SOLID_BSP &&
  611. (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
  612. {
  613. vec3_t a;
  614. vec3_t forward, right, up;
  615. vec3_t temp;
  616. if (trace.fraction != 1)
  617. {
  618. VectorSubtract (vec3_origin, ent->v.angles, a);
  619. AngleVectors (a, forward, right, up);
  620. VectorCopy (trace.endpos, temp);
  621. trace.endpos[0] = DotProduct (temp, forward);
  622. trace.endpos[1] = -DotProduct (temp, right);
  623. trace.endpos[2] = DotProduct (temp, up);
  624. VectorCopy (trace.plane.normal, temp);
  625. trace.plane.normal[0] = DotProduct (temp, forward);
  626. trace.plane.normal[1] = -DotProduct (temp, right);
  627. trace.plane.normal[2] = DotProduct (temp, up);
  628. }
  629. }
  630. #endif
  631. // fix trace up by the offset
  632. if (trace.fraction != 1)
  633. VectorAdd (trace.endpos, offset, trace.endpos);
  634. // did we clip the move?
  635. if (trace.fraction < 1 || trace.startsolid )
  636. trace.ent = ent;
  637. return trace;
  638. }
  639. //===========================================================================
  640. /*
  641. ====================
  642. SV_ClipToLinks
  643. Mins and maxs enclose the entire area swept by the move
  644. ====================
  645. */
  646. void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip )
  647. {
  648. link_t *l, *next;
  649. edict_t *touch;
  650. trace_t trace;
  651. // touch linked edicts
  652. for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
  653. {
  654. next = l->next;
  655. touch = EDICT_FROM_AREA(l);
  656. if (touch->v.solid == SOLID_NOT)
  657. continue;
  658. if (touch == clip->passedict)
  659. continue;
  660. if (touch->v.solid == SOLID_TRIGGER)
  661. Sys_Error ("Trigger in clipping list");
  662. if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP)
  663. continue;
  664. if (clip->boxmins[0] > touch->v.absmax[0]
  665. || clip->boxmins[1] > touch->v.absmax[1]
  666. || clip->boxmins[2] > touch->v.absmax[2]
  667. || clip->boxmaxs[0] < touch->v.absmin[0]
  668. || clip->boxmaxs[1] < touch->v.absmin[1]
  669. || clip->boxmaxs[2] < touch->v.absmin[2] )
  670. continue;
  671. if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0])
  672. continue; // points never interact
  673. // might intersect, so do an exact clip
  674. if (clip->trace.allsolid)
  675. return;
  676. if (clip->passedict)
  677. {
  678. if (PROG_TO_EDICT(touch->v.owner) == clip->passedict)
  679. continue; // don't clip against own missiles
  680. if (PROG_TO_EDICT(clip->passedict->v.owner) == touch)
  681. continue; // don't clip against owner
  682. }
  683. if ((int)touch->v.flags & FL_MONSTER)
  684. trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end);
  685. else
  686. trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end);
  687. if (trace.allsolid || trace.startsolid ||
  688. trace.fraction < clip->trace.fraction)
  689. {
  690. trace.ent = touch;
  691. if (clip->trace.startsolid)
  692. {
  693. clip->trace = trace;
  694. clip->trace.startsolid = true;
  695. }
  696. else
  697. clip->trace = trace;
  698. }
  699. else if (trace.startsolid)
  700. clip->trace.startsolid = true;
  701. }
  702. // recurse down both sides
  703. if (node->axis == -1)
  704. return;
  705. if ( clip->boxmaxs[node->axis] > node->dist )
  706. SV_ClipToLinks ( node->children[0], clip );
  707. if ( clip->boxmins[node->axis] < node->dist )
  708. SV_ClipToLinks ( node->children[1], clip );
  709. }
  710. /*
  711. ==================
  712. SV_MoveBounds
  713. ==================
  714. */
  715. void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
  716. {
  717. #if 0
  718. // debug to test against everything
  719. boxmins[0] = boxmins[1] = boxmins[2] = -9999;
  720. boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999;
  721. #else
  722. int i;
  723. for (i=0 ; i<3 ; i++)
  724. {
  725. if (end[i] > start[i])
  726. {
  727. boxmins[i] = start[i] + mins[i] - 1;
  728. boxmaxs[i] = end[i] + maxs[i] + 1;
  729. }
  730. else
  731. {
  732. boxmins[i] = end[i] + mins[i] - 1;
  733. boxmaxs[i] = start[i] + maxs[i] + 1;
  734. }
  735. }
  736. #endif
  737. }
  738. /*
  739. ==================
  740. SV_Move
  741. ==================
  742. */
  743. trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict)
  744. {
  745. moveclip_t clip;
  746. int i;
  747. memset ( &clip, 0, sizeof ( moveclip_t ) );
  748. // clip to world
  749. clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end );
  750. clip.start = start;
  751. clip.end = end;
  752. clip.mins = mins;
  753. clip.maxs = maxs;
  754. clip.type = type;
  755. clip.passedict = passedict;
  756. if (type == MOVE_MISSILE)
  757. {
  758. for (i=0 ; i<3 ; i++)
  759. {
  760. clip.mins2[i] = -15;
  761. clip.maxs2[i] = 15;
  762. }
  763. }
  764. else
  765. {
  766. VectorCopy (mins, clip.mins2);
  767. VectorCopy (maxs, clip.maxs2);
  768. }
  769. // create the bounding box of the entire move
  770. SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
  771. // clip to entities
  772. SV_ClipToLinks ( sv_areanodes, &clip );
  773. return clip.trace;
  774. }