LCOV - code coverage report
Current view: top level - engine/world - mpr.cpp (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 0 163 0.0 %
Date: 2024-11-22 05:07:59 Functions: 0 33 0.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 1.14