home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / pmovetst.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  9.3 KB  |  415 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "quakedef.h"
  21.  
  22. static    hull_t        box_hull;
  23. static    dclipnode_t    box_clipnodes[6];
  24. static    mplane_t    box_planes[6];
  25.  
  26. extern    vec3_t player_mins;
  27. extern    vec3_t player_maxs;
  28.  
  29. /*
  30. ===================
  31. PM_InitBoxHull
  32.  
  33. Set up the planes and clipnodes so that the six floats of a bounding box
  34. can just be stored out and get a proper hull_t structure.
  35. ===================
  36. */
  37. void PM_InitBoxHull (void)
  38. {
  39.     int        i;
  40.     int        side;
  41.  
  42.     box_hull.clipnodes = box_clipnodes;
  43.     box_hull.planes = box_planes;
  44.     box_hull.firstclipnode = 0;
  45.     box_hull.lastclipnode = 5;
  46.  
  47.     for (i=0 ; i<6 ; i++)
  48.     {
  49.         box_clipnodes[i].planenum = i;
  50.         
  51.         side = i&1;
  52.         
  53.         box_clipnodes[i].children[side] = CONTENTS_EMPTY;
  54.         if (i != 5)
  55.             box_clipnodes[i].children[side^1] = i + 1;
  56.         else
  57.             box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
  58.         
  59.         box_planes[i].type = i>>1;
  60.         box_planes[i].normal[i>>1] = 1;
  61.     }
  62.     
  63. }
  64.  
  65.  
  66. /*
  67. ===================
  68. PM_HullForBox
  69.  
  70. To keep everything totally uniform, bounding boxes are turned into small
  71. BSP trees instead of being compared directly.
  72. ===================
  73. */
  74. hull_t    *PM_HullForBox (vec3_t mins, vec3_t maxs)
  75. {
  76.     box_planes[0].dist = maxs[0];
  77.     box_planes[1].dist = mins[0];
  78.     box_planes[2].dist = maxs[1];
  79.     box_planes[3].dist = mins[1];
  80.     box_planes[4].dist = maxs[2];
  81.     box_planes[5].dist = mins[2];
  82.  
  83.     return &box_hull;
  84. }
  85.  
  86.  
  87. /*
  88. ==================
  89. PM_HullPointContents
  90.  
  91. ==================
  92. */
  93. int PM_HullPointContents (hull_t *hull, int num, vec3_t p)
  94. {
  95.     float        d;
  96.     dclipnode_t    *node;
  97.     mplane_t    *plane;
  98.  
  99.     while (num >= 0)
  100.     {
  101.         if (num < hull->firstclipnode || num > hull->lastclipnode)
  102.             Sys_Error ("PM_HullPointContents: bad node number");
  103.     
  104.         node = hull->clipnodes + num;
  105.         plane = hull->planes + node->planenum;
  106.         
  107.         if (plane->type < 3)
  108.             d = p[plane->type] - plane->dist;
  109.         else
  110.             d = DotProduct (plane->normal, p) - plane->dist;
  111.         if (d < 0)
  112.             num = node->children[1];
  113.         else
  114.             num = node->children[0];
  115.     }
  116.     
  117.     return num;
  118. }
  119.  
  120. /*
  121. ==================
  122. PM_PointContents
  123.  
  124. ==================
  125. */
  126. int PM_PointContents (vec3_t p)
  127. {
  128.     float        d;
  129.     dclipnode_t    *node;
  130.     mplane_t    *plane;
  131.     hull_t        *hull;
  132.     int            num;
  133.  
  134.     hull = &pmove.physents[0].model->hulls[0];
  135.  
  136.     num = hull->firstclipnode;
  137.  
  138.     while (num >= 0)
  139.     {
  140.         if (num < hull->firstclipnode || num > hull->lastclipnode)
  141.             Sys_Error ("PM_HullPointContents: bad node number");
  142.     
  143.         node = hull->clipnodes + num;
  144.         plane = hull->planes + node->planenum;
  145.         
  146.         if (plane->type < 3)
  147.             d = p[plane->type] - plane->dist;
  148.         else
  149.             d = DotProduct (plane->normal, p) - plane->dist;
  150.         if (d < 0)
  151.             num = node->children[1];
  152.         else
  153.             num = node->children[0];
  154.     }
  155.     
  156.     return num;
  157. }
  158.  
  159. /*
  160. ===============================================================================
  161.  
  162. LINE TESTING IN HULLS
  163.  
  164. ===============================================================================
  165. */
  166.  
  167. // 1/32 epsilon to keep floating point happy
  168. #define    DIST_EPSILON    (0.03125)
  169.  
  170. /*
  171. ==================
  172. PM_RecursiveHullCheck
  173.  
  174. ==================
  175. */
  176. qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace)
  177. {
  178.     dclipnode_t    *node;
  179.     mplane_t    *plane;
  180.     float        t1, t2;
  181.     float        frac;
  182.     int            i;
  183.     vec3_t        mid;
  184.     int            side;
  185.     float        midf;
  186.  
  187. // check for empty
  188.     if (num < 0)
  189.     {
  190.         if (num != CONTENTS_SOLID)
  191.         {
  192.             trace->allsolid = false;
  193.             if (num == CONTENTS_EMPTY)
  194.                 trace->inopen = true;
  195.             else
  196.                 trace->inwater = true;
  197.         }
  198.         else
  199.             trace->startsolid = true;
  200.         return true;        // empty
  201.     }
  202.  
  203.     if (num < hull->firstclipnode || num > hull->lastclipnode)
  204.         Sys_Error ("PM_RecursiveHullCheck: bad node number");
  205.  
  206. //
  207. // find the point distances
  208. //
  209.     node = hull->clipnodes + num;
  210.     plane = hull->planes + node->planenum;
  211.  
  212.     if (plane->type < 3)
  213.     {
  214.         t1 = p1[plane->type] - plane->dist;
  215.         t2 = p2[plane->type] - plane->dist;
  216.     }
  217.     else
  218.     {
  219.         t1 = DotProduct (plane->normal, p1) - plane->dist;
  220.         t2 = DotProduct (plane->normal, p2) - plane->dist;
  221.     }
  222.     
  223. #if 1
  224.     if (t1 >= 0 && t2 >= 0)
  225.         return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
  226.     if (t1 < 0 && t2 < 0)
  227.         return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
  228. #else
  229.     if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
  230.         return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
  231.     if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
  232.         return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
  233. #endif
  234.  
  235. // put the crosspoint DIST_EPSILON pixels on the near side
  236.     if (t1 < 0)
  237.         frac = (t1 + DIST_EPSILON)/(t1-t2);
  238.     else
  239.         frac = (t1 - DIST_EPSILON)/(t1-t2);
  240.     if (frac < 0)
  241.         frac = 0;
  242.     if (frac > 1)
  243.         frac = 1;
  244.         
  245.     midf = p1f + (p2f - p1f)*frac;
  246.     for (i=0 ; i<3 ; i++)
  247.         mid[i] = p1[i] + frac*(p2[i] - p1[i]);
  248.  
  249.     side = (t1 < 0);
  250.  
  251. // move up to the node
  252.     if (!PM_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
  253.         return false;
  254.  
  255. #ifdef PARANOID
  256.     if (PM_HullPointContents (pm_hullmodel, mid, node->children[side])
  257.     == CONTENTS_SOLID)
  258.     {
  259.         Con_Printf ("mid PointInHullSolid\n");
  260.         return false;
  261.     }
  262. #endif
  263.     
  264.     if (PM_HullPointContents (hull, node->children[side^1], mid)
  265.     != CONTENTS_SOLID)
  266. // go past the node
  267.         return PM_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
  268.     
  269.     if (trace->allsolid)
  270.         return false;        // never got out of the solid area
  271.         
  272. //==================
  273. // the other side of the node is solid, this is the impact point
  274. //==================
  275.     if (!side)
  276.     {
  277.         VectorCopy (plane->normal, trace->plane.normal);
  278.         trace->plane.dist = plane->dist;
  279.     }
  280.     else
  281.     {
  282.         VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
  283.         trace->plane.dist = -plane->dist;
  284.     }
  285.  
  286.     while (PM_HullPointContents (hull, hull->firstclipnode, mid)
  287.     == CONTENTS_SOLID)
  288.     { // shouldn't really happen, but does occasionally
  289.         frac -= 0.1;
  290.         if (frac < 0)
  291.         {
  292.             trace->fraction = midf;
  293.             VectorCopy (mid, trace->endpos);
  294.             Con_DPrintf ("backup past 0\n");
  295.             return false;
  296.         }
  297.         midf = p1f + (p2f - p1f)*frac;
  298.         for (i=0 ; i<3 ; i++)
  299.             mid[i] = p1[i] + frac*(p2[i] - p1[i]);
  300.     }
  301.  
  302.     trace->fraction = midf;
  303.     VectorCopy (mid, trace->endpos);
  304.  
  305.     return false;
  306. }
  307.  
  308.  
  309. /*
  310. ================
  311. PM_TestPlayerPosition
  312.  
  313. Returns false if the given player position is not valid (in solid)
  314. ================
  315. */
  316. qboolean PM_TestPlayerPosition (vec3_t pos)
  317. {
  318.     int            i;
  319.     physent_t    *pe;
  320.     vec3_t        mins, maxs, test;
  321.     hull_t        *hull;
  322.  
  323.     for (i=0 ; i< pmove.numphysent ; i++)
  324.     {
  325.         pe = &pmove.physents[i];
  326.     // get the clipping hull
  327.         if (pe->model)
  328.             hull = &pmove.physents[i].model->hulls[1];
  329.         else
  330.         {
  331.             VectorSubtract (pe->mins, player_maxs, mins);
  332.             VectorSubtract (pe->maxs, player_mins, maxs);
  333.             hull = PM_HullForBox (mins, maxs);
  334.         }
  335.  
  336.         VectorSubtract (pos, pe->origin, test);
  337.  
  338.         if (PM_HullPointContents (hull, hull->firstclipnode, test) == CONTENTS_SOLID)
  339.             return false;
  340.     }
  341.  
  342.     return true;
  343. }
  344.  
  345. /*
  346. ================
  347. PM_PlayerMove
  348. ================
  349. */
  350. pmtrace_t PM_PlayerMove (vec3_t start, vec3_t end)
  351. {
  352.     pmtrace_t        trace, total;
  353.     vec3_t        offset;
  354.     vec3_t        start_l, end_l;
  355.     hull_t        *hull;
  356.     int            i;
  357.     physent_t    *pe;
  358.     vec3_t        mins, maxs;
  359.  
  360. // fill in a default trace
  361.     memset (&total, 0, sizeof(pmtrace_t));
  362.     total.fraction = 1;
  363.     total.ent = -1;
  364.     VectorCopy (end, total.endpos);
  365.  
  366.     for (i=0 ; i< pmove.numphysent ; i++)
  367.     {
  368.         pe = &pmove.physents[i];
  369.     // get the clipping hull
  370.         if (pe->model)
  371.             hull = &pmove.physents[i].model->hulls[1];
  372.         else
  373.         {
  374.             VectorSubtract (pe->mins, player_maxs, mins);
  375.             VectorSubtract (pe->maxs, player_mins, maxs);
  376.             hull = PM_HullForBox (mins, maxs);
  377.         }
  378.  
  379.     // PM_HullForEntity (ent, mins, maxs, offset);
  380.     VectorCopy (pe->origin, offset);
  381.  
  382.         VectorSubtract (start, offset, start_l);
  383.         VectorSubtract (end, offset, end_l);
  384.  
  385.     // fill in a default trace
  386.         memset (&trace, 0, sizeof(pmtrace_t));
  387.         trace.fraction = 1;
  388.         trace.allsolid = true;
  389. //        trace.startsolid = true;
  390.         VectorCopy (end, trace.endpos);
  391.  
  392.     // trace a line through the apropriate clipping hull
  393.         PM_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
  394.  
  395.         if (trace.allsolid)
  396.             trace.startsolid = true;
  397.         if (trace.startsolid)
  398.             trace.fraction = 0;
  399.  
  400.     // did we clip the move?
  401.         if (trace.fraction < total.fraction)
  402.         {
  403.             // fix trace up by the offset
  404.             VectorAdd (trace.endpos, offset, trace.endpos);
  405.             total = trace;
  406.             total.ent = i;
  407.         }
  408.  
  409.     }
  410.  
  411.     return total;
  412. }
  413.  
  414.  
  415.