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

Generated by: LCOV version 2.0-1