LCOV - code coverage report
Current view: top level - engine/model - ragdoll.h (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 100.0 % 2 2
Test Date: 2025-05-25 06:55:32 Functions: 100.0 % 2 2

            Line data    Source code
       1              : #ifndef RAGDOLL_H_
       2              : #define RAGDOLL_H_
       3              : 
       4              : /**
       5              :  * @brief A representation of a ragdoll for a class of models.
       6              :  *
       7              :  * ragdollskel defines a skeletal animation object for use by skelmodel, which
       8              :  * is able to be dynamically modified by physics (rather than by an animation file)
       9              :  *
      10              :  * ragdollskel objects are owned by skelmodel::skeleton objects and therefore there
      11              :  * is exactly one `ragdollskel` no matter how many entities use a particular model
      12              :  */
      13              : 
      14              : class ragdollskel final
      15              : {
      16              :     public:
      17            5 :         ragdollskel() : loaded(false), animjoints(false), eye(-1) {}
      18              : 
      19              :         bool loaded, animjoints;
      20              : 
      21              :         struct tri final
      22              :         {
      23              :             int vert[3];
      24              : 
      25              :             /**
      26              :              * @brief Determines whether two tris share any vertex indices.
      27              :              *
      28              :              * Returns true if the the passed triangle has any of the same vertex indices,
      29              :              * regardless of order (e.g. if this.vert[0] and t.vert[2] are the same, returns true)
      30              :              *
      31              :              * @param t the tri to compare to
      32              :              *
      33              :              * @return true if any indices from this are the same as any from t
      34              :              * @return false if no vertex indices match
      35              :              */
      36              :             bool shareverts(const tri &t) const;
      37              :         };
      38              :         std::vector<tri> tris;
      39              : 
      40              :         struct reljoint final
      41              :         {
      42              :             int bone, parent;
      43              :         };
      44              :         std::vector<reljoint> reljoints;
      45              : 
      46              :         struct vert final
      47              :         {
      48              :             vec pos;
      49              :             float radius, weight;
      50              :         };
      51              :         std::vector<vert> verts;
      52              : 
      53              :         struct joint final
      54              :         {
      55              :             int bone, tri, vert[3];
      56              :             float weight;
      57              :             matrix4x3 orient;
      58              :         };
      59              :         std::vector<joint> joints;
      60              : 
      61              :         struct rotlimit final
      62              :         {
      63              :             int tri[2];
      64              :             float maxangle, maxtrace;
      65              :             matrix3 middle;
      66              :         };
      67              :         std::vector<rotlimit> rotlimits;
      68              : 
      69              :         struct rotfriction final
      70              :         {
      71              :             int tri[2];
      72              :         };
      73              :         std::vector<rotfriction> rotfrictions;
      74              : 
      75              :         //a distance constraint between two specified vertices
      76              :         //vert specifies the indices of the vertices in the verts vector, and
      77              :         //min/maxdist the limits to keep them within
      78              :         struct distlimit final
      79              :         {
      80              :             int vert[2];
      81              :             float mindist, maxdist;
      82              :         };
      83              :         std::vector<distlimit> distlimits;
      84              : 
      85              :         int eye;
      86              : 
      87              :         void setup();
      88              :         void addreljoint(int bone, int parent);
      89              : 
      90              :     private:
      91              :         void setupjoints();
      92              : 
      93              :         /**
      94              :          * @brief Adds indices for rotation frictions.
      95              :          *
      96              :          * For each pair of triangles in the tris vector of this object where one or more
      97              :          * vertices in those two triangles refer to the same vertex, adds a new rotfriction
      98              :          * to the rotfrictions vector with those triangles' indices within the tris vector.
      99              :          *
     100              :          * The rotfrictions vector is cleared before adding these entries; does not append
     101              :          * to existing entries that may be present.
     102              :          */
     103              :         void setuprotfrictions();
     104              : };
     105              : 
     106              : /**
     107              :  * @brief An individual instantiation of a ragdoll for a skeletal model
     108              :  *
     109              :  * ragdolldata defines a class corresponding to a specific instantiation of a ragdoll
     110              :  * in the context of a dynent. Many ragdolldata objects may point to the same ragdollskel
     111              :  * object.
     112              :  */
     113              : class ragdolldata final
     114              : {
     115              :     public:
     116              :         const ragdollskel *skel;
     117              :         int millis, collidemillis, lastmove;
     118              :         float radius;
     119              :         vec offset, center;
     120              : 
     121              :         //shadows the elements in skel->tris, should not be resized after construction
     122              :         std::vector<matrix3> tris;
     123              : 
     124              :         //shadows the elements in skel->animjoints
     125              :         matrix4x3 *animjoints;
     126              : 
     127              :         //shadows the elements in skel->reljoints
     128              :         dualquat *reljoints;
     129              : 
     130              :         struct vert final
     131              :         {
     132              :             vec oldpos, pos, newpos, undo;
     133              :             float weight;
     134              :             bool collided, stuck;
     135            5 :             vert() : oldpos(0, 0, 0), pos(0, 0, 0), newpos(0, 0, 0), undo(0, 0, 0), weight(0), collided(false), stuck(true) {}
     136              :         };
     137              : 
     138              :         //shadows the elements in skel->verts, should not be resized after construction
     139              :         std::vector<vert> verts;
     140              : 
     141              :         ragdolldata(const ragdollskel *skel, float scale = 1);
     142              :         ~ragdolldata();
     143              : 
     144              :         /**
     145              :          * @brief Moves the joints of the ragdoll.
     146              :          *
     147              :          * Moves the ragdoll joints by an amount indicated by the amount of time
     148              :          * passed to `ts`. The ragdoll movement will be calculated using
     149              :          * the ragdollwaterfric variable if water is true, and ragdollairfric if not.
     150              :          *
     151              :          * @param water whether the ragdoll is moving through air (false) or water(true)
     152              :          * @param ts the time to use to calculate physics with, in seconds
     153              :          */
     154              :         void move(bool water, float ts);
     155              : 
     156              :         /**
     157              :          * @brief Returns a transformation matrix according to the animation matrix and position
     158              :          *
     159              :          * Assumes that there are joints to use to calcuate.
     160              :          *
     161              :          * @param i the index of the joint to calculate
     162              :          * @param anim the animation matrix to transform the joint with
     163              :          *
     164              :          * @return an orientation matrix corresponding to the animation data passed
     165              :          */
     166              :         matrix4x3 calcanimjoint(int i, const matrix4x3 &anim) const;
     167              :         void init(const dynent *d);
     168              : 
     169              :     private:
     170              :         int collisions, floating, unsticks;
     171              :         float timestep, scale;
     172              : 
     173              :         std::vector<matrix3> rotfrictions;
     174              : 
     175              :         /**
     176              :          * @brief Sets new values in the tris matrix vector based on ragdollskel tris
     177              :          *
     178              :          * Const with respect to all values outside of the vector of tris
     179              :          *
     180              :          * Reads values from the associated ragdollskel, and sets the vecs inside the
     181              :          * corresponding matrix in the ragdolldata as follows:
     182              :          *
     183              :          *               /|
     184              :          *              /
     185              :          *          m.c/
     186              :          *            /
     187              :          *        v1 /   m.a     v2
     188              :          *          *---------->*
     189              :          *          |
     190              :          *          |
     191              :          *          |
     192              :          *       m.b|
     193              :          *          v
     194              :          *
     195              :          *
     196              :          *          *
     197              :          *           v3
     198              :          *
     199              :          *        ----→    ----→
     200              :          *  m.c = v1 v2  x v1 v3
     201              :          *        --→   ----→
     202              :          *  m.b = m.c x v1 v2
     203              :          *
     204              :          * m.a points from v1 to v2
     205              :          * m.b points from v1 to v3
     206              :          * m.c points along the normal of the triangle v1, v2, v3
     207              :          *
     208              :          * Prior values that may be in the matrix vector are disregarded and have no
     209              :          * effect on the output values.
     210              :          */
     211              :         void calctris();
     212              : 
     213              :         /**
     214              :          * @brief Calculates the ragdolldata's radius and center position
     215              :          *
     216              :          * Sets the center position to be the average of all the vertices in the ragdoll
     217              :          * Sets the radius to be the distance between the center and the farthest vert
     218              :          *
     219              :          * This is not necessarily the smallest sphere encapsulating all of the points
     220              :          * in the vertex array, since that would be the midpoint of the farthest points in
     221              :          * the vertex array.
     222              :          */
     223              :         void calcboundsphere();
     224              :         void constrain(vec &cwall);
     225              : 
     226              :         /**
     227              :          * @brief Adds weights to keep pairs of vertices within specified bounds
     228              :          *
     229              :          * For each vertex pair in the defined distlimits vector, adds weights to
     230              :          * those verts to pull or push those vertices to lie within the specified min/maxdist
     231              :          * distance apart.
     232              :          *
     233              :          * Modifies vertex weights and newpos fields and no other components of ragdolldata.
     234              :          */
     235              :         void constraindist();
     236              : 
     237              :         /**
     238              :          * @brief Applies a rotation around a specified axis to a pair of triangles.
     239              :          *
     240              :          * Modifies the vertices pointed to by the two assigned tri objects by rotating them
     241              :          * to the amount indicated by the angle and about the axis specified by axis.
     242              :          *
     243              :          * For each vertex indicated by the indices in the triangle objects, adds to the
     244              :          * newpos vec a value corresponding to the rotation desired. Increments the weight
     245              :          * field for each vertex so modified by one. Does not modify the vert's pos or oldpos,
     246              :          * only newpos.
     247              :          *
     248              :          * @param t1 the first triangle to retrieve vertices with
     249              :          * @param t2 the second triangle to retrieve vertices with
     250              :          * @param angle the angle in radians to rotate by
     251              :          * @param axis the axis by which to rotate around
     252              :          */
     253              :         void applyrotlimit(const ragdollskel::tri &t1, const ragdollskel::tri &t2, float angle, const vec &axis);
     254              : 
     255              :         /**
     256              :          * @brief Calculates and applies a rotation limit each defined rotation limit
     257              :          *
     258              :          * For each rotlimit in the associated skeleton, calculates the angle and rotation
     259              :          * from that rotlimit and applies it to the associated vertices.
     260              :          */
     261              :         void constrainrot();
     262              : 
     263              :         /**
     264              :          * @brief Sets the shadowing elements in rotfrictions according to their respective values in the pointed ragdollskel.
     265              :          *
     266              :          * For each member of ragdolldata::rotfrictions, sets its value to the transposed multiplication of
     267              :          * the data pointed to by the indices of the first two vertices in the ragdollskel::rotfrictions tri data.
     268              :          *
     269              :          * Previous values in ragdolldata::rotfrictions are ignored and overwritten.
     270              :          */
     271              :         void calcrotfriction();
     272              : 
     273              :         /**
     274              :          * @brief Applies rotation friction and propagates it to the model's vertices
     275              :          *
     276              :          * Calculates rotation limits with applyrotlimit() and then moves the set `newpos`
     277              :          * values to the `pos` values in each vert.
     278              :          *
     279              :          * @param ts the time duration to apply in seconds
     280              :          */
     281              :         void applyrotfriction(float ts);
     282              : 
     283              :         /**
     284              :          * @brief Modifies stuck verticies in the vertex array.
     285              :          *
     286              :          * Only affects those vertices which have the `stuck` field set to `true`.
     287              :          *
     288              :          * Moves those `stuck` vertices towards the average position of the unstuck vertices,
     289              :          * with a magnitude equal to the `speed` parameter.
     290              :          *
     291              :          * @param speed the magnitude by which to modify stuck vertices
     292              :          *
     293              :          */
     294              :         void tryunstick(float speed, vec &cwall);
     295              : 
     296              :         /**
     297              :          * @brief Checks collision of `dir` with spherical volume at `pos` with radius `radius`.
     298              :          *
     299              :          * Checks collision of defined sphere with the cubeworld, in direction `dir`.
     300              :          * physics' `collide()` used for collision detection against the cubeworld.
     301              :          *
     302              :          * @param pos positon of sphere center
     303              :          * @param dir direction to check collision against
     304              :          * @param radius radius of sphere center
     305              :          * @param [out] cwall collision wall data found by the collision check
     306              :          *
     307              :          * @return true if collision occured
     308              :          * @return false if no collision occured
     309              :          */
     310              :         static bool collidevert(const vec &pos, const vec &dir, float radius, vec &cwall);
     311              : };
     312              : 
     313              : /**
     314              :  * @brief Deletes the heap-allocated ragdoll associated with the passed dynent.
     315              :  *
     316              :  * If there is no ragdoll associated with `d`, then there is no effect.
     317              :  *
     318              :  * @param d the dynent to delete the ragdoll of
     319              :  */
     320              : extern void cleanragdoll(dynent *d);
     321              : 
     322              : #endif
        

Generated by: LCOV version 2.0-1