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 : class ragdollskel final
11 : {
12 : public:
13 5 : ragdollskel() : loaded(false), animjoints(false), eye(-1) {}
14 :
15 : bool loaded, animjoints;
16 :
17 : struct tri final
18 : {
19 : int vert[3];
20 :
21 : /**
22 : * @brief Determines whether two tris share any vertex indices.
23 : *
24 : * Returns true if the the passed triangle has any of the same vertex indices,
25 : * regardless of order (e.g. if this.vert[0] and t.vert[2] are the same, returns true)
26 : *
27 : * @param t the tri to compare to
28 : *
29 : * @return true if any indices from this are the same as any from t
30 : * @return false if no vertex indices match
31 : */
32 : bool shareverts(const tri &t) const;
33 : };
34 : std::vector<tri> tris;
35 :
36 : struct reljoint final
37 : {
38 : int bone, parent;
39 : };
40 : std::vector<reljoint> reljoints;
41 :
42 : struct vert final
43 : {
44 : vec pos;
45 : float radius, weight;
46 : };
47 : std::vector<vert> verts;
48 :
49 : struct joint final
50 : {
51 : int bone, tri, vert[3];
52 : float weight;
53 : matrix4x3 orient;
54 : };
55 : std::vector<joint> joints;
56 :
57 : struct rotlimit final
58 : {
59 : int tri[2];
60 : float maxangle, maxtrace;
61 : matrix3 middle;
62 : };
63 : std::vector<rotlimit> rotlimits;
64 :
65 : struct rotfriction final
66 : {
67 : int tri[2];
68 : };
69 : std::vector<rotfriction> rotfrictions;
70 :
71 : struct distlimit final
72 : {
73 : int vert[2];
74 : float mindist, maxdist;
75 : };
76 : std::vector<distlimit> distlimits;
77 :
78 : int eye;
79 :
80 : void setup();
81 : void addreljoint(int bone, int parent);
82 :
83 : private:
84 : void setupjoints();
85 :
86 : /**
87 : * @brief Adds indices for rotation frictions.
88 : *
89 : * For each pair of triangles in the tris vector of this object where one or more
90 : * vertices in those two triangles refer to the same vertex, adds a new rotfriction
91 : * to the rotfrictions vector with those triangles' indices within the tris vector.
92 : *
93 : * The rotfrictions vector is cleared before adding these entries; does not append
94 : * to existing entries that may be present.
95 : */
96 : void setuprotfrictions();
97 : };
98 :
99 : /*
100 : * ragdolldata defines a class corresponding to a specific instantiation of a ragdoll
101 : * in the context of a dynent. Many ragdolldata objects may point to the same ragdollskel
102 : * object.
103 : */
104 : class ragdolldata final
105 : {
106 : public:
107 : const ragdollskel *skel;
108 : int millis, collidemillis, lastmove;
109 : float radius;
110 : vec offset, center;
111 :
112 : //shadows the elements in skel->tris, should not be resized after construction
113 : std::vector<matrix3> tris;
114 :
115 : //shadows the elements in skel->animjoints
116 : matrix4x3 *animjoints;
117 :
118 : //shadows the elements in skel->reljoints
119 : dualquat *reljoints;
120 :
121 : struct vert final
122 : {
123 : vec oldpos, pos, newpos, undo;
124 : float weight;
125 : bool collided, stuck;
126 5 : vert() : oldpos(0, 0, 0), pos(0, 0, 0), newpos(0, 0, 0), undo(0, 0, 0), weight(0), collided(false), stuck(true) {}
127 : };
128 :
129 : //shadows the elements in skel->verts, should not be resized after construction
130 : std::vector<vert> verts;
131 :
132 : ragdolldata(const ragdollskel *skel, float scale = 1);
133 : ~ragdolldata();
134 :
135 : void move(bool water, float ts);
136 :
137 : /**
138 : * @brief Sets the ragdolldata::animjoints matrix element at index i according to the animation matrix and position
139 : *
140 : * Const with respect to all other fields within ragdolldata other than animjoints[i].
141 : *
142 : * The value set at animjoints[i] is not dependent on the value of animjoints[i]
143 : * prior to the calculation.
144 : *
145 : * @param i the index of the joint to calculate
146 : * @param anim the animation matrix to transform the joint with
147 : */
148 : void calcanimjoint(int i, const matrix4x3 &anim);
149 : void init(const dynent *d);
150 :
151 : private:
152 : int collisions, floating, unsticks;
153 : float timestep, scale;
154 :
155 : std::vector<matrix3> rotfrictions;
156 :
157 : /**
158 : * @brief Sets new values in the tris matrix vector based on ragdollskel tris
159 : *
160 : * Const with respect to all values outside of the vector of tris
161 : *
162 : * Reads values from the associated ragdollskel, and sets the vecs inside the
163 : * corresponding matrix in the ragdolldata as follows:
164 : *
165 : * /|
166 : * /
167 : * m.c/
168 : * /
169 : * v1 / m.a v2
170 : * *---------->*
171 : * |
172 : * |
173 : * |
174 : * m.b|
175 : * v
176 : *
177 : *
178 : * *
179 : * v3
180 : *
181 : * ----→ ----→
182 : * m.c = v1 v2 x v1 v3
183 : * --→ ----→
184 : * m.b = m.c x v1 v2
185 : *
186 : * m.a points from v1 to v2
187 : * m.b points from v1 to v3
188 : * m.c points along the normal of the triangle v1, v2, v3
189 : *
190 : * Prior values that may be in the matrix vector are disregarded and have no
191 : * effect on the output values.
192 : */
193 : void calctris();
194 :
195 : /**
196 : * @brief Calculates the ragdolldata's radius and center position
197 : *
198 : * Sets the center position to be the average of all the vertices in the ragdoll
199 : * Sets the radius to be the distance between the center and the farthest vert
200 : *
201 : * This is not necessarily the smallest sphere encapsulating all of the points
202 : * in the vertex array, since that would be the midpoint of the farthest points in
203 : * the vertex array.
204 : */
205 : void calcboundsphere();
206 : void constrain();
207 : void constraindist();
208 :
209 : /**
210 : * @brief Applies a rotation around a specified axis to a pair of triangles.
211 : *
212 : * Modifies the vertices pointed to by the two assigned tri objects by rotating them
213 : * to the amount indicated by the angle and about the axis specified by axis.
214 : *
215 : * @param t1 the first triangle to modify
216 : * @param t2 the second triangle to modify
217 : * @param angle the angle to rotate by
218 : * @param axis the axis by which to rotate around
219 : */
220 : void applyrotlimit(const ragdollskel::tri &t1, const ragdollskel::tri &t2, float angle, const vec &axis);
221 : void constrainrot();
222 : void calcrotfriction();
223 : void applyrotfriction(float ts);
224 :
225 : /**
226 : * @brief Modifies stuck verticies in the vertex array.
227 : *
228 : * Only affects those vertices which have the `stuck` field set to `true`.
229 : *
230 : * Moves those `stuck` vertices towards the average position of the unstuck vertices,
231 : * with a magnitude equal to the `speed` parameter.
232 : *
233 : * @param speed the magnitude by which to modify stuck vertices
234 : *
235 : */
236 : void tryunstick(float speed);
237 :
238 : /**
239 : * @brief Checks collision of `dir` with spherical volume at `pos` with radius `radius`.
240 : *
241 : * Checks collision of defined sphere with the cubeworld, in direction `dir`.
242 : * physics' `collide()` used for collision detection against the cubeworld.
243 : *
244 : * @param pos positon of sphere center
245 : * @param dir direction to check collision against
246 : * @param radius radius of sphere center
247 : *
248 : * @return true if collision occured
249 : * @return false if no collision occured
250 : */
251 : static bool collidevert(const vec &pos, const vec &dir, float radius);
252 : };
253 :
254 : extern void cleanragdoll(dynent *d);
255 :
256 : #endif
|