LCOV - code coverage report
Current view: top level - engine/world - raycube.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.0 % 290 0
Test Date: 2025-02-21 06:59:27 Functions: 0.0 % 19 0

            Line data    Source code
       1              : 
       2              : /////////////////////////  ray - cube collision ///////////////////////////////////////////////
       3              : 
       4              : //functions for finding where vectors hit world geometry on the octree
       5              : 
       6              : /* Unlike vector geometry, finding collision with world surfaces has to interact with the
       7              :  * octree geometry. Octree geometry behaves differently for identifying collision due to
       8              :  * its recursive behavior, and as a result the algorithms for identifying collision with
       9              :  * the world looks different than other world geometry systems.
      10              :  *
      11              :  * Octree cube collision is necessary for physics (as players need to interact with the world geometry)
      12              :  * and for other world interaction by players (e.g. identifying where structure in the world is)
      13              :  */
      14              : #include "../libprimis-headers/cube.h"
      15              : #include "../../shared/geomexts.h"
      16              : 
      17              : #include "bih.h"
      18              : #include "entities.h"
      19              : #include "octaworld.h"
      20              : #include "raycube.h"
      21              : #include "world/world.h"
      22              : 
      23              : //internally relevant functionality
      24              : namespace
      25              : {
      26            0 :     clipplanes &getclipplanes(const cube &c, const ivec &o, int size)
      27              :     {
      28            0 :         clipplanes &p = rootworld.getclipbounds(c, o, size, c.visible&0x80 ? 2 : 0);
      29            0 :         if(p.visible&0x80)
      30              :         {
      31            0 :             genclipplanes(c, o, size, p, false, false);
      32              :         }
      33            0 :         return p;
      34              :     }
      35              : 
      36              :     //============================================================= INTERSECTBOX
      37              : 
      38            0 :     static bool intersectplanes(const clipplanes& p, const vec &v, const vec& ray, float &enterdist, float &exitdist, int &entry)
      39              :     {
      40            0 :         for(int i = 0; i < p.size; ++i)
      41              :         {
      42            0 :             float pdist = p.p[i].dist(v),
      43            0 :                   facing = ray.dot(p.p[i]);
      44            0 :             if(facing < 0)
      45              :             {
      46            0 :                 pdist /= -facing;
      47            0 :                 if(pdist > enterdist)
      48              :                 {
      49            0 :                     if(pdist > exitdist)
      50              :                     {
      51            0 :                         return false;
      52              :                     }
      53            0 :                     enterdist = pdist;
      54            0 :                     entry = i;
      55              :                 }
      56              :             }
      57            0 :             else if(facing > 0)
      58              :             {
      59            0 :                 pdist /= -facing;
      60            0 :                 if(pdist < exitdist)
      61              :                 {
      62            0 :                     if(pdist < enterdist)
      63              :                     {
      64            0 :                         return false;
      65              :                     }
      66            0 :                     exitdist = pdist;
      67              :                 }
      68              :             }
      69            0 :             else if(pdist > 0)
      70              :             {
      71            0 :                 return false;
      72              :             }
      73              :         }
      74            0 :         return true;
      75              :     }
      76              : 
      77            0 :     static bool intersectbox(const clipplanes& p, const vec &v, const vec& ray, const vec& invray, float &enterdist, float &exitdist, int &entry)
      78              :     {
      79            0 :         for(int i = 0; i < 3; ++i)
      80              :         {
      81            0 :             if(ray[i])
      82              :             {
      83            0 :                 float prad = std::fabs(p.r[i] * invray[i]),
      84            0 :                       pdist = (p.o[i] - v[i]) * invray[i],
      85            0 :                       pmin = pdist - prad,
      86            0 :                       pmax = pdist + prad;
      87            0 :                 if(pmin > enterdist)
      88              :                 {
      89            0 :                     if(pmin > exitdist)
      90              :                     {
      91            0 :                         return false;
      92              :                     }
      93            0 :                     enterdist = pmin;
      94            0 :                     entry = i;
      95              :                 }
      96            0 :                 if(pmax < exitdist)
      97              :                 {
      98            0 :                     if(pmax < enterdist)
      99              :                     {
     100            0 :                         return false;
     101              :                     }
     102            0 :                     exitdist = pmax;
     103              :                 }
     104              :             }
     105            0 :             else if(v[i] < p.o[i]-p.r[i] || v[i] > p.o[i]+p.r[i])
     106              :             {
     107            0 :                 return false;
     108              :             }
     109              :         }
     110            0 :         return true;
     111              :     }
     112              : 
     113            0 :     bool raycubeintersect(const clipplanes &p, const vec &v, const vec &ray, const vec &invray, float maxdist, float &dist)
     114              :     {
     115            0 :         int entry   = -1,
     116            0 :             bbentry = -1;
     117            0 :         float enterdist = -1e16f,
     118            0 :               exitdist  = 1e16f;
     119            0 :         if(!intersectplanes(p, v, ray, enterdist, exitdist, entry))
     120              :         {
     121            0 :             return false;
     122              :         }
     123            0 :         if(!intersectbox(p, v, ray, invray, enterdist, exitdist, bbentry))
     124              :         {
     125            0 :             return false;
     126              :         }
     127            0 :         if(exitdist < 0)
     128              :         {
     129            0 :             return false;
     130              :         }
     131            0 :         dist = std::max(enterdist+0.1f, 0.0f);
     132            0 :         if(dist < maxdist)
     133              :         {
     134            0 :             if(bbentry>=0)
     135              :             {
     136            0 :                 hitsurface = vec(0, 0, 0);
     137            0 :                 hitsurface[bbentry] = ray[bbentry]>0 ? -1 : 1;
     138              :             }
     139              :             else
     140              :             {
     141            0 :                 hitsurface = p.p[entry];
     142              :             }
     143              :         }
     144            0 :         return true;
     145              :     }
     146              : 
     147              :     float hitentdist;
     148              :     int hitent, hitorient;
     149              : 
     150            0 :     float disttoent(const octaentities *oc, const vec &o, const vec &ray, float radius, int mode, const extentity *t)
     151              :     {
     152            0 :         vec eo, es;
     153            0 :         int orient = -1;
     154            0 :         float dist = radius,
     155            0 :               f = 0.0f;
     156            0 :         const std::vector<extentity *> &ents = entities::getents();
     157              :     //=======ENT_SEL_INTERSECT ENT_INTERSECT
     158              :         #define ENT_INTERSECT(type, func) do { \
     159              :             for(size_t i = 0; i < oc->type.size(); i++) \
     160              :             { \
     161              :                 extentity &e = *ents[oc->type[i]]; \
     162              :                 if(!(e.flags&EntFlag_Octa) || &e==t) \
     163              :                 { \
     164              :                     continue; \
     165              :                 } \
     166              :                 func; \
     167              :                 if(f < dist && f > 0 && vec(ray).mul(f).add(o).insidebb(oc->o, oc->size)) \
     168              :                 { \
     169              :                     hitentdist = dist = f; \
     170              :                     hitent = oc->type[i]; \
     171              :                     hitorient = orient; \
     172              :                 } \
     173              :             } \
     174              :         } while(0)
     175              : 
     176            0 :         if((mode&Ray_Poly) == Ray_Poly)
     177              :         {
     178            0 :             ENT_INTERSECT(mapmodels,
     179              :             {
     180              :                 if(!mmintersect(e, o, ray, radius, mode, f))
     181              :                 {
     182              :                     continue;
     183              :                 }
     184              :             });
     185              :         }
     186              : 
     187              :         #define ENT_SEL_INTERSECT(type) ENT_INTERSECT(type, { \
     188              :             entselectionbox(e, eo, es); \
     189              :             if(!rayboxintersect(eo, es, o, ray, f, orient)) \
     190              :             { \
     191              :                 continue; \
     192              :             } \
     193              :         })
     194              : 
     195            0 :         if((mode&Ray_Ents) == Ray_Ents)
     196              :         {
     197            0 :             ENT_SEL_INTERSECT(other);
     198            0 :             ENT_SEL_INTERSECT(mapmodels);
     199            0 :             ENT_SEL_INTERSECT(decals);
     200              :         }
     201              : 
     202            0 :         return dist;
     203              :     }
     204              :     #undef ENT_INTERSECT
     205              :     #undef ENT_SEL_INTERSECT
     206              :     //======================================
     207            0 :     float disttooutsideent(const vec &o, const vec &ray, float radius, const extentity *t)
     208              :     {
     209            0 :         vec eo, es;
     210              :         int orient;
     211            0 :         float dist = radius,
     212            0 :               f = 0.0f;
     213            0 :         const std::vector<extentity *> &ents = entities::getents();
     214            0 :         for(const int &i : outsideents)
     215              :         {
     216            0 :             const extentity &e = *ents[i];
     217            0 :             if(!(e.flags&EntFlag_Octa) || &e == t)
     218              :             {
     219            0 :                 continue;
     220              :             }
     221            0 :             entselectionbox(e, eo, es);
     222            0 :             if(!rayboxintersect(eo, es, o, ray, f, orient))
     223              :             {
     224            0 :                 continue;
     225              :             }
     226            0 :             if(f < dist && f > 0)
     227              :             {
     228            0 :                 hitentdist = dist = f;
     229            0 :                 hitent = outsideents[i];
     230            0 :                 hitorient = orient;
     231              :             }
     232              :         }
     233            0 :         return dist;
     234              :     }
     235              : 
     236              :     // optimized shadow version
     237            0 :     float shadowent(const octaentities *oc, const vec &o, const vec &ray, float radius, int mode, const extentity *t)
     238              :     {
     239            0 :         float dist = radius,
     240            0 :               f = 0.0f;
     241            0 :         const std::vector<extentity *> &ents = entities::getents();
     242            0 :         for(const int &i : oc->mapmodels)
     243              :         {
     244            0 :             const extentity &e = *ents[i];
     245            0 :             if(!(e.flags&EntFlag_Octa) || &e==t)
     246              :             {
     247            0 :                 continue;
     248              :             }
     249            0 :             if(!mmintersect(e, o, ray, radius, mode, f))
     250              :             {
     251            0 :                 continue;
     252              :             }
     253            0 :             if(f > 0 && f < dist)
     254              :             {
     255            0 :                 dist = f;
     256              :             }
     257              :         }
     258            0 :         return dist;
     259              :     }
     260              : }
     261              : 
     262              : //externally relevant functionality
     263            0 : bool insideworld(const vec &o)
     264              : {
     265            0 :     return o.x>=0 && o.x<rootworld.mapsize() && o.y>=0 && o.y<rootworld.mapsize() && o.z>=0 && o.z<rootworld.mapsize();
     266              : }
     267              : 
     268            0 : bool insideworld(const ivec &o)
     269              : {
     270            0 :     return static_cast<uint>(o.x) < static_cast<uint>(rootworld.mapsize()) &&
     271            0 :            static_cast<uint>(o.y) < static_cast<uint>(rootworld.mapsize()) &&
     272            0 :            static_cast<uint>(o.z) < static_cast<uint>(rootworld.mapsize());
     273              : }
     274              : 
     275              : vec hitsurface;
     276              : 
     277              : //will only change &outrad and &dist if not inside the world
     278              : //true if outside world, false if inside
     279            0 : bool cubeworld::checkinsideworld(const vec &invray, float radius, float &outrad, const vec &o, vec &v, const vec& ray, float &dist) const
     280              : {
     281            0 :     if(!insideworld(o))
     282              :     {
     283            0 :         float disttoworld = 0,
     284            0 :               exitworld = 1e16f;
     285            0 :         for(int i = 0; i < 3; ++i)
     286              :         {
     287            0 :             float c = v[i];
     288            0 :             if(c<0 || c>=mapsize())
     289              :             {
     290            0 :                 float d = ((invray[i]>0?0:mapsize())-c)*invray[i];
     291            0 :                 if(d<0)
     292              :                 {
     293            0 :                     outrad =  radius>0 ? radius :-1;
     294            0 :                     return true;
     295              :                 }
     296            0 :                 disttoworld = std::max(disttoworld, 0.1f + d);
     297              :             }
     298            0 :             float e = ((invray[i]>0?mapsize():0)-c)*invray[i];
     299            0 :             exitworld = std::min(exitworld, e);
     300              :         }
     301            0 :         if(disttoworld > exitworld)
     302              :         {
     303            0 :             outrad = (radius>0?radius:-1);
     304            0 :             return true;
     305              :         }
     306            0 :         v.add(vec(ray).mul(disttoworld));
     307            0 :         dist += disttoworld;
     308              :     }
     309            0 :     return false;
     310              : }
     311              : 
     312            0 : static void findclosest(int &closest, int xval, int yval, int zval, const ivec &lsizemask, const vec &invray, const ivec &lo, const int &lshift, vec &v, float &dist, const vec& ray)
     313              : {
     314            0 :         float dx = (lo.x+(lsizemask.x<<lshift)-v.x)*invray.x,
     315            0 :               dy = (lo.y+(lsizemask.y<<lshift)-v.y)*invray.y,
     316            0 :               dz = (lo.z+(lsizemask.z<<lshift)-v.z)*invray.z;
     317            0 :         float disttonext = dx;
     318            0 :         closest = xval;
     319            0 :         if(dy < disttonext)
     320              :         {
     321            0 :             disttonext = dy;
     322            0 :             closest = yval;
     323              :         }
     324            0 :         if(dz < disttonext)
     325              :         {
     326            0 :             disttonext = dz;
     327            0 :             closest = zval;
     328              :         }
     329            0 :         disttonext += 0.1f;
     330            0 :         v.add(vec(ray).mul(disttonext));
     331            0 :         dist += disttonext;
     332            0 : }
     333              : 
     334            0 : bool cubeworld::upoctree(const vec& v, int& x, int& y, int& z, const ivec& lo, int& lshift) const
     335              : {
     336            0 :     x = static_cast<int>(v.x);
     337            0 :     y = static_cast<int>(v.y);
     338            0 :     z = static_cast<int>(v.z);
     339            0 :     uint diff = static_cast<uint>(lo.x^x)|static_cast<uint>(lo.y^y)|static_cast<uint>(lo.z^z);
     340            0 :     if(diff >= static_cast<uint>(mapsize()))
     341              :     {
     342            0 :         return true;
     343              :     }
     344            0 :     diff >>= lshift;
     345            0 :     if(!diff)
     346              :     {
     347            0 :         return true;
     348              :     }
     349              :     do
     350              :     {
     351            0 :         lshift++;
     352            0 :         diff >>= 1;
     353            0 :     } while(diff);
     354            0 :     return false;
     355              : }
     356              : 
     357              : //======================================================= DOWNOCTREE INITRAYCUBE
     358              : 
     359              : #define DOWNOCTREE(disttoent, earlyexit) \
     360              :         cube *lc = r.levels[r.lshift]; \
     361              :         for(;;) \
     362              :         { \
     363              :             r.lshift--; \
     364              :             lc += OCTA_STEP(x, y, z, r.lshift); \
     365              :             if(lc->ext && lc->ext->ents && r.lshift < r.elvl) \
     366              :             { \
     367              :                 float edist = disttoent(lc->ext->ents, o, ray, r.dent, mode, t); \
     368              :                 if(edist < r.dent) \
     369              :                 { \
     370              :                     earlyexit return std::min(edist, r.dist); \
     371              :                     r.elvl = r.lshift; \
     372              :                     r.dent = std::min(r.dent, edist); \
     373              :                 } \
     374              :             } \
     375              :             if(lc->children==nullptr) \
     376              :             { \
     377              :                 break; \
     378              :             } \
     379              :             lc = &(*lc->children)[0]; \
     380              :             r.levels[r.lshift] = lc; \
     381              :         }
     382              : 
     383              : //NOTE: levels[20] magically assumes mapscale <20
     384              : #define INITRAYCUBE \
     385              :     float dist = 0, \
     386              :           dent = radius > 0 ? radius : 1e16f; \
     387              :     vec v(o), \
     388              :         invray(ray.x ? 1/ray.x : 1e16f, ray.y ? 1/ray.y : 1e16f, ray.z ? 1/ray.z : 1e16f); \
     389              :     cube *levels[20]; \
     390              :     levels[worldscale] = &(*worldroot)[0]; \
     391              :     int lshift = worldscale, \
     392              :         elvl = mode&Ray_BB ? worldscale : 0; \
     393              :     ivec lsizemask(invray.x>0 ? 1 : 0, invray.y>0 ? 1 : 0, invray.z>0 ? 1 : 0);
     394              : 
     395              : struct raycubeinfo
     396              : {
     397              :     float dist,
     398              :           dent;
     399              :     vec v,
     400              :         invray;
     401              :     cube *levels[20];
     402              :     int lshift,
     403              :         elvl;
     404              :     ivec lsizemask;
     405              : 
     406            0 :     raycubeinfo(float radius, const vec &o, const vec &ray, int worldscale, int mode, cube *r)
     407            0 :     {
     408            0 :         dist = 0;
     409            0 :         dent = radius > 0 ? radius : 1e16f;
     410            0 :         v = o;
     411            0 :         invray = vec(ray.x ? 1/ray.x : 1e16f, ray.y ? 1/ray.y : 1e16f, ray.z ? 1/ray.z : 1e16f);
     412            0 :         levels[worldscale] = r;
     413            0 :         lshift = worldscale;
     414            0 :         elvl = mode&Ray_BB ? worldscale : 0;
     415            0 :         lsizemask = ivec(invray.x>0 ? 1 : 0, invray.y>0 ? 1 : 0, invray.z>0 ? 1 : 0);
     416            0 :     }
     417              : };
     418              : 
     419            0 : float cubeworld::raycube(const vec &o, const vec &ray, float radius, int mode, int size, const extentity *t) const
     420              : {
     421            0 :     if(ray.iszero())
     422              :     {
     423            0 :         return 0;
     424              :     }
     425            0 :     raycubeinfo r(radius, o, ray, worldscale, mode, &(*worldroot)[0]);
     426              :     //scope limiting brackets
     427              :     {
     428            0 :         float outrad = 0.f;
     429            0 :         if(checkinsideworld(r.invray, radius, outrad, o, r.v, ray, r.dist))
     430              :         {
     431            0 :             return outrad;
     432              :         }
     433              :     }
     434            0 :     int closest = -1,
     435            0 :         x = static_cast<int>(r.v.x),
     436            0 :         y = static_cast<int>(r.v.y),
     437            0 :         z = static_cast<int>(r.v.z);
     438              :     for(;;)
     439              :     {
     440            0 :         DOWNOCTREE(disttoent, if(mode&Ray_Shadow));
     441              : 
     442            0 :         int lsize = 1<<r.lshift;
     443              : 
     444            0 :         cube &c = *lc;
     445            0 :         if((r.dist>0 || !(mode&Ray_SkipFirst)) &&
     446            0 :            (((mode&Ray_ClipMat) && IS_CLIPPED(c.material&MatFlag_Volume)) ||
     447            0 :             ((mode&Ray_EditMat) && c.material != Mat_Air) ||
     448            0 :             (!(mode&Ray_Pass) && lsize==size && !(c.isempty())) ||
     449            0 :             c.issolid() ||
     450            0 :             r.dent < r.dist) &&
     451            0 :             (!(mode&Ray_ClipMat) || (c.material&MatFlag_Clip)!=Mat_NoClip))
     452              :         {
     453            0 :             if(r.dist < r.dent)
     454              :             {
     455            0 :                 if(closest < 0)
     456              :                 {
     457            0 :                     float dx = ((x&(~0U<<r.lshift))+(r.invray.x>0 ? 0 : 1<<r.lshift)-r.v.x)*r.invray.x,
     458            0 :                           dy = ((y&(~0U<<r.lshift))+(r.invray.y>0 ? 0 : 1<<r.lshift)-r.v.y)*r.invray.y,
     459            0 :                           dz = ((z&(~0U<<r.lshift))+(r.invray.z>0 ? 0 : 1<<r.lshift)-r.v.z)*r.invray.z;
     460            0 :                     closest = dx > dy ? (dx > dz ? 0 : 2) : (dy > dz ? 1 : 2);
     461              :                 }
     462            0 :                 hitsurface = vec(0, 0, 0);
     463            0 :                 hitsurface[closest] = ray[closest]>0 ? -1 : 1;
     464            0 :                 return r.dist;
     465              :             }
     466            0 :             return r.dent;
     467              :         }
     468              : 
     469            0 :         ivec lo(x&(~0U<<r.lshift),
     470            0 :              y&(~0U<<r.lshift),
     471            0 :              z&(~0U<<r.lshift));
     472              : 
     473            0 :         if(!(c.isempty()))
     474              :         {
     475            0 :             const clipplanes &p = getclipplanes(c, lo, lsize);
     476            0 :             float f = 0;
     477            0 :             if(raycubeintersect(p, r.v, ray, r.invray, r.dent-r.dist, f) && (r.dist+f>0 || !(mode&Ray_SkipFirst)) && (!(mode&Ray_ClipMat) || (c.material&MatFlag_Clip)!=Mat_NoClip))
     478              :             {
     479            0 :                 return std::min(r.dent, r.dist+f);
     480              :             }
     481              :         }
     482            0 :         findclosest(closest, 0, 1, 2, r.lsizemask, r.invray, lo, r.lshift, r.v, r.dist, ray);
     483            0 :         if(radius>0 && r.dist>=radius)
     484              :         {
     485            0 :             return std::min(r.dent, r.dist);
     486              :         }
     487            0 :         if(upoctree(r.v, x, y, z, lo, r.lshift))
     488              :         {
     489            0 :             return std::min(r.dent, radius>0 ? radius : r.dist);
     490              :         }
     491            0 :     }
     492              : }
     493              : 
     494              : // optimized version for light shadowing... every cycle here counts!!!
     495            0 : float cubeworld::shadowray(const vec &o, const vec &ray, float radius, int mode, const extentity *t)
     496              : {
     497            0 :     raycubeinfo r(radius, o, ray, worldscale, mode, &(*worldroot)[0]);
     498              :     //scope limiting brackets
     499              :     {
     500            0 :         float outrad = 0.f;
     501            0 :         if(checkinsideworld(r.invray, radius, outrad, o, r.v, ray, r.dist))
     502              :         {
     503            0 :             return outrad;
     504              :         }
     505              :     }
     506            0 :     int side = Orient_Bottom,
     507            0 :         x = static_cast<int>(r.v.x),
     508            0 :         y = static_cast<int>(r.v.y),
     509            0 :         z = static_cast<int>(r.v.z);
     510              :     for(;;)
     511              :     {
     512            0 :         DOWNOCTREE(shadowent, );
     513              : 
     514            0 :         const cube &c = *lc;
     515            0 :         ivec lo(x&(~0U<<r.lshift),
     516            0 :              y&(~0U<<r.lshift),
     517            0 :              z&(~0U<<r.lshift));
     518              : 
     519            0 :         if(!(c.isempty()) && !(c.material&Mat_Alpha))
     520              :         {
     521            0 :             if(c.issolid())
     522              :             {
     523            0 :                 return c.texture[side]==Default_Sky && mode&Ray_SkipSky ? radius : r.dist;
     524              :             }
     525            0 :             const clipplanes &p = getclipplanes(c, lo, 1<<r.lshift);
     526            0 :             float enterdist = -1e16f,
     527            0 :                   exitdist  = 1e16f;
     528            0 :             int i = 0;
     529            0 :             bool intersected = intersectplanes(p, r.v, ray, enterdist, exitdist, i);
     530            0 :             side = p.side[i];
     531            0 :             if(!intersected)
     532              :             {
     533            0 :                 goto nextcube;
     534              :             }
     535            0 :             intersected = intersectbox(p, r.v, ray, r.invray, enterdist, exitdist, i);
     536            0 :             side = (i<<1) + 1 - r.lsizemask[i];
     537            0 :             if(!intersected)
     538              :             {
     539            0 :                 goto nextcube;
     540              :             }
     541            0 :             if(exitdist >= 0)
     542              :             {
     543            0 :                 return c.texture[side]==Default_Sky && mode&Ray_SkipSky ? radius : r.dist+std::max(enterdist+0.1f, 0.0f);
     544              :             }
     545              :         }
     546              : 
     547            0 :     nextcube:
     548            0 :         findclosest(side, Orient_Right - r.lsizemask.x, Orient_Front - r.lsizemask.y, Orient_Top - r.lsizemask.z, r.lsizemask, r.invray, lo, r.lshift, r.v, r.dist, ray);
     549            0 :         if(r.dist>=radius)
     550              :         {
     551            0 :             return r.dist;
     552              :         }
     553            0 :         if(upoctree(r.v, x, y, z, lo, r.lshift))
     554              :         {
     555            0 :             return radius;
     556              :         }
     557            0 :     }
     558              : }
     559              : #undef DOWNOCTREE
     560              : //==============================================================================
     561            0 : float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int &orient, int &ent)
     562              : {
     563            0 :     hitent = -1;
     564            0 :     hitentdist = radius;
     565            0 :     hitorient = -1;
     566            0 :     float dist = rootworld.raycube(o, ray, radius, mode, size);
     567            0 :     if((mode&Ray_Ents) == Ray_Ents)
     568              :     {
     569            0 :         float dent = disttooutsideent(o, ray, dist < 0 ? 1e16f : dist, nullptr);
     570            0 :         if(dent < 1e15f && (dist < 0 || dent < dist))
     571              :         {
     572            0 :             dist = dent;
     573              :         }
     574              :     }
     575            0 :     orient = hitorient;
     576            0 :     ent = hitentdist == dist ? hitent : -1;
     577            0 :     return dist;
     578              : }
     579              : 
     580            0 : float raycubepos(const vec &o, const vec &ray, vec &hitpos, float radius, int mode, int size)
     581              : {
     582            0 :     hitpos = ray;
     583            0 :     float dist = rootworld.raycube(o, ray, radius, mode, size);
     584            0 :     if(radius>0 && dist>=radius)
     585              :     {
     586            0 :         dist = radius;
     587              :     }
     588            0 :     hitpos.mul(dist).add(o);
     589            0 :     return dist;
     590              : }
     591              : 
     592            0 : bool raycubelos(const vec &o, const vec &dest, vec &hitpos)
     593              : {
     594            0 :     vec ray(dest);
     595            0 :     ray.sub(o);
     596            0 :     float mag = ray.magnitude();
     597            0 :     ray.mul(1/mag);
     598            0 :     float distance = raycubepos(o, ray, hitpos, mag, Ray_ClipMat|Ray_Poly);
     599            0 :     return distance >= mag;
     600              : }
     601              : 
     602            0 : float rayfloor(const vec &o, vec &floor, int mode, float radius)
     603              : {
     604            0 :     if(o.z<=0)
     605              :     {
     606            0 :         return -1;
     607              :     }
     608            0 :     hitsurface = vec(0, 0, 1);
     609            0 :     float dist = rootworld.raycube(o, vec(0, 0, -1), radius, mode);
     610            0 :     if(dist<0 || (radius>0 && dist>=radius))
     611              :     {
     612            0 :         return dist;
     613              :     }
     614            0 :     floor = hitsurface;
     615            0 :     return dist;
     616              : }
        

Generated by: LCOV version 2.0-1