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: 2026-08-20 06:51:03 Functions: 100.0 % 2 2

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

Generated by: LCOV version 2.0-1