LCOV - code coverage report
Current view: top level - engine/world - mpr.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.0 % 163 0
Test Date: 2025-02-18 06:21:28 Functions: 0.0 % 33 0

            Line data    Source code
       1              : /*This code is based off the Minkowski Portal Refinement algorithm by Gary Snethen
       2              :  * in XenoCollide & Game Programming Gems 7.
       3              :  *
       4              :  * Minkowski Portal Refinement is a way of finding whether two hulls intersect
       5              :  * efficiently, useful for finding if two models are intersecting quickly
       6              :  *
       7              :  * used in physics.cpp and for model-related collision purposes
       8              :  */
       9              : #include "../libprimis-headers/cube.h"
      10              : #include "../../shared/geomexts.h"
      11              : 
      12              : #include "octaworld.h"
      13              : 
      14              : #include "mpr.h"
      15              : 
      16              : namespace mpr
      17              : {
      18              : 
      19              :     //CubePlanes
      20              : 
      21            0 :     vec CubePlanes::center() const
      22              :     {
      23            0 :         return p.o;
      24              :     }
      25              : 
      26            0 :     vec CubePlanes::supportpoint(const vec &n) const
      27              :     {
      28            0 :         int besti = 7;
      29            0 :         float bestd = n.dot(p.v[7]);
      30            0 :         for(int i = 0; i < 7; ++i)
      31              :         {
      32            0 :             float d = n.dot(p.v[i]);
      33            0 :             if(d > bestd)
      34              :             {
      35            0 :                 besti = i;
      36            0 :                 bestd = d;
      37              :             }
      38              :         }
      39            0 :         return p.v[besti];
      40              :     }
      41              : 
      42              :     //SolidCube
      43              : 
      44            0 :     vec SolidCube::center() const
      45              :     {
      46            0 :         return vec(o).add(size/2);
      47              :     }
      48              : 
      49            0 :     vec SolidCube::supportpoint (const vec &n) const
      50              :     {
      51            0 :         vec p(o);
      52            0 :         if(n.x > 0)
      53              :         {
      54            0 :             p.x += size;
      55              :         }
      56            0 :         if(n.y > 0)
      57              :         {
      58            0 :             p.y += size;
      59              :         }
      60            0 :         if(n.z > 0)
      61              :         {
      62            0 :             p.z += size;
      63              :         }
      64            0 :         return p;
      65              :     }
      66              : 
      67              :     //Ent
      68              : 
      69            0 :     vec Ent::center() const
      70              :     {
      71            0 :         return vec(ent->o.x, ent->o.y, ent->o.z + (ent->aboveeye - ent->eyeheight)/2);
      72              :     }
      73              : 
      74              :     //EntOBB
      75              : 
      76            0 :     EntOBB::EntOBB(const physent *ent) : Ent(ent)
      77              :     {
      78            0 :         orient.setyaw(ent->yaw/RAD);
      79            0 :     }
      80              : 
      81            0 :     vec EntOBB::contactface(const vec &wn, const vec &wdir) const
      82              :     {
      83            0 :         vec n = orient.transform(wn).div(vec(ent->xradius, ent->yradius, (ent->aboveeye + ent->eyeheight)/2)),
      84            0 :             dir = orient.transform(wdir),
      85            0 :             an(std::fabs(n.x), std::fabs(n.y), dir.z ? std::fabs(n.z) : 0),
      86            0 :             fn(0, 0, 0);
      87            0 :         if(an.x > an.y)
      88              :         {
      89            0 :             if(an.x > an.z)
      90              :             {
      91            0 :                 fn.x = n.x*dir.x < 0 ? (n.x > 0 ? 1 : -1) : 0;
      92              :             }
      93            0 :             else if(an.z > 0)
      94              :             {
      95            0 :                 fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
      96              :             }
      97              :         }
      98            0 :         else if(an.y > an.z)
      99              :         {
     100            0 :             fn.y = n.y*dir.y < 0 ? (n.y > 0 ? 1 : -1) : 0;
     101              :         }
     102            0 :         else if(an.z > 0)
     103              :         {
     104            0 :             fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
     105              :         }
     106            0 :         return orient.transposedtransform(fn);
     107              :     }
     108              : 
     109            0 :     vec EntOBB::localsupportpoint(const vec &ln) const
     110              :     {
     111            0 :         return vec(ln.x > 0 ? ent->xradius : -ent->xradius,
     112            0 :                    ln.y > 0 ? ent->yradius : -ent->yradius,
     113            0 :                    ln.z > 0 ? ent->aboveeye : -ent->eyeheight);
     114              :     }
     115            0 :     vec EntOBB::supportpoint(const vec &n) const
     116              :     {
     117            0 :         return orient.transposedtransform(localsupportpoint(orient.transform(n))).add(ent->o);
     118              :     }
     119              : 
     120            0 :     float EntOBB::supportcoordneg(const vec &p) const
     121              :     {
     122            0 :         return localsupportpoint(vec(p).neg()).dot(p);
     123              :     }
     124              : 
     125            0 :     float EntOBB::supportcoord(const vec &p) const
     126              :     {
     127            0 :         return localsupportpoint(p).dot(p);
     128              :     }
     129              : 
     130            0 :     float EntOBB::left()   const { return supportcoordneg(orient.a) + ent->o.x; }
     131            0 :     float EntOBB::right()  const { return supportcoord(orient.a) + ent->o.x; }
     132            0 :     float EntOBB::back()   const { return supportcoordneg(orient.b) + ent->o.y; }
     133            0 :     float EntOBB::front()  const { return supportcoord(orient.b) + ent->o.y; }
     134            0 :     float EntOBB::bottom() const { return ent->o.z - ent->eyeheight; }
     135            0 :     float EntOBB::top()    const { return ent->o.z + ent->aboveeye; }
     136              : 
     137              :     //EntFuzzy
     138              : 
     139            0 :     float EntFuzzy::left()   const { return ent->o.x - ent->radius; }
     140            0 :     float EntFuzzy::right()  const { return ent->o.x + ent->radius; }
     141            0 :     float EntFuzzy::back()   const { return ent->o.y - ent->radius; }
     142            0 :     float EntFuzzy::front()  const { return ent->o.y + ent->radius; }
     143            0 :     float EntFuzzy::bottom() const { return ent->o.z - ent->eyeheight; }
     144            0 :     float EntFuzzy::top()    const { return ent->o.z + ent->aboveeye; }
     145              : 
     146              :     //EntCylinder
     147              : 
     148            0 :     vec EntCylinder::contactface(const vec &n, const vec &dir) const
     149              :     {
     150            0 :         float dxy = n.dot2(n)/(ent->radius*ent->radius),
     151            0 :               dz = n.z*n.z*4/(ent->aboveeye + ent->eyeheight);
     152            0 :         vec fn(0, 0, 0);
     153            0 :         if(dz > dxy && dir.z)
     154              :         {
     155            0 :             fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
     156              :         }
     157            0 :         else if(n.dot2(dir) < 0)
     158              :         {
     159            0 :             fn.x = n.x;
     160            0 :             fn.y = n.y;
     161            0 :             fn.normalize();
     162              :         }
     163            0 :         return fn;
     164              :     }
     165              : 
     166            0 :     vec EntCylinder::supportpoint(const vec &n) const
     167              :     {
     168            0 :         vec p(ent->o);
     169            0 :         if(n.z > 0)
     170              :         {
     171            0 :             p.z += ent->aboveeye;
     172              :         }
     173              :         else
     174              :         {
     175            0 :             p.z -= ent->eyeheight;
     176              :         }
     177            0 :         if(n.x || n.y)
     178              :         {
     179            0 :             float r = ent->radius / n.magnitude2();
     180            0 :             p.x += n.x*r;
     181            0 :             p.y += n.y*r;
     182              :         }
     183            0 :         return p;
     184              :     }
     185              : 
     186              :     //EntCapsule
     187              : 
     188            0 :     vec EntCapsule::supportpoint(const vec &n) const
     189              :     {
     190            0 :         vec p(ent->o);
     191            0 :         if(n.z > 0)
     192              :         {
     193            0 :             p.z += ent->aboveeye - ent->radius;
     194              :         }
     195              :         else
     196              :         {
     197            0 :             p.z -= ent->eyeheight - ent->radius;
     198              :         }
     199            0 :         p.add(vec(n).mul(ent->radius / n.magnitude()));
     200            0 :         return p;
     201              :     }
     202              : 
     203              :     //EntEllipsoid
     204              : 
     205            0 :     vec EntEllipsoid::supportpoint(const vec &dir) const
     206              :     {
     207            0 :         vec p(ent->o);
     208            0 :         vec n = vec(dir).normalize();
     209            0 :         p.x += ent->radius*n.x;
     210            0 :         p.y += ent->radius*n.y;
     211            0 :         p.z += (ent->aboveeye + ent->eyeheight)/2*(1 + n.z) - ent->eyeheight;
     212            0 :         return p;
     213              :     }
     214              : 
     215              :     //Model
     216              : 
     217            0 :     Model::Model(const vec &ent, const vec &center, const vec &radius, int yaw, int pitch, int roll) : o(ent), radius(radius)
     218              :     {
     219            0 :         orient.identity();
     220            0 :         if(roll)
     221              :         {
     222            0 :             orient.rotate_around_y(sincosmod360(roll));
     223              :         }
     224            0 :         if(pitch)
     225              :         {
     226            0 :             orient.rotate_around_x(sincosmod360(-pitch));
     227              :         }
     228            0 :         if(yaw)
     229              :         {
     230            0 :             orient.rotate_around_z(sincosmod360(-yaw));
     231              :         }
     232            0 :         o.add(orient.transposedtransform(center));
     233            0 :     }
     234              : 
     235            0 :     vec Model::center() const
     236              :     {
     237            0 :         return o;
     238              :     }
     239              : 
     240              :     //ModelOBB
     241              : 
     242            0 :     vec ModelOBB::contactface(const vec &wn, const vec &wdir) const
     243              :     {
     244            0 :         vec n = orient.transform(wn).div(radius),
     245            0 :             dir = orient.transform(wdir),
     246            0 :             an(std::fabs(n.x), std::fabs(n.y), dir.z ? std::fabs(n.z) : 0),
     247            0 :             fn(0, 0, 0);
     248            0 :         if(an.x > an.y)
     249              :         {
     250            0 :             if(an.x > an.z)
     251              :             {
     252            0 :                 fn.x = n.x*dir.x < 0 ? (n.x > 0 ? 1 : -1) : 0;
     253              :             }
     254            0 :             else if(an.z > 0)
     255              :             {
     256            0 :                 fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
     257              :             }
     258              :         }
     259            0 :         else if(an.y > an.z)
     260              :         {
     261            0 :             fn.y = n.y*dir.y < 0 ? (n.y > 0 ? 1 : -1) : 0;
     262              :         }
     263            0 :         else if(an.z > 0)
     264              :         {
     265            0 :             fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
     266              :         }
     267            0 :         return orient.transposedtransform(fn);
     268              :     }
     269              : 
     270            0 :     vec ModelOBB::supportpoint(const vec &n) const
     271              :     {
     272            0 :         vec ln = orient.transform(n),
     273            0 :             p(0, 0, 0);
     274            0 :         if(ln.x > 0)
     275              :         {
     276            0 :             p.x += radius.x;
     277              :         }
     278              :         else
     279              :         {
     280            0 :             p.x -= radius.x;
     281              :         }
     282            0 :         if(ln.y > 0)
     283              :         {
     284            0 :             p.y += radius.y;
     285              :         }
     286              :         else
     287              :         {
     288            0 :             p.y -= radius.y;
     289              :         }
     290            0 :         if(ln.z > 0)
     291              :         {
     292            0 :             p.z += radius.z;
     293              :         }
     294              :         else
     295              :         {
     296            0 :             p.z -= radius.z;
     297              :         }
     298            0 :         return orient.transposedtransform(p).add(o);
     299              :     }
     300              : 
     301              :     //ModelEllipse
     302              : 
     303            0 :     vec ModelEllipse::contactface(const vec &wn, const vec &wdir) const
     304              :     {
     305            0 :         vec n = orient.transform(wn).div(radius),
     306            0 :             dir = orient.transform(wdir);
     307            0 :         float dxy = n.dot2(n),
     308            0 :               dz = n.z*n.z;
     309            0 :         vec fn(0, 0, 0);
     310            0 :         if(dz > dxy && dir.z)
     311              :         {
     312            0 :             fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
     313              :         }
     314            0 :         else if(n.dot2(dir) < 0)
     315              :         {
     316            0 :             fn.x = n.x*radius.y;
     317            0 :             fn.y = n.y*radius.x;
     318            0 :             fn.normalize();
     319              :         }
     320            0 :         return orient.transposedtransform(fn);
     321              :     }
     322              : 
     323            0 :     vec ModelEllipse::supportpoint(const vec &n) const
     324              :     {
     325            0 :         vec ln = orient.transform(n),
     326            0 :             p(0, 0, 0);
     327            0 :         if(ln.z > 0)
     328              :         {
     329            0 :             p.z += radius.z;
     330              :         }
     331              :         else
     332              :         {
     333            0 :             p.z -= radius.z;
     334              :         }
     335            0 :         if(ln.x || ln.y)
     336              :         {
     337            0 :             float r = ln.magnitude2();
     338            0 :             p.x += ln.x*radius.x/r;
     339            0 :             p.y += ln.y*radius.y/r;
     340              :         }
     341            0 :         return orient.transposedtransform(p).add(o);
     342              :     }
     343              : }
        

Generated by: LCOV version 2.0-1