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-02-18 06:21:28 Functions: 100.0 % 2 2

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

Generated by: LCOV version 2.0-1