1 | /* |
2 | * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. |
3 | * |
4 | * NVIDIA CORPORATION and its licensors retain all intellectual property |
5 | * and proprietary rights in and to this software, related documentation |
6 | * and any modifications thereto. Any use, reproduction, disclosure or |
7 | * distribution of this software and related documentation without an express |
8 | * license agreement from NVIDIA CORPORATION is strictly prohibited. |
9 | */ |
10 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
11 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
12 | |
13 | |
14 | #ifndef PX_EXTENSIONS_JOINT_LIMIT |
15 | #define PX_EXTENSIONS_JOINT_LIMIT |
16 | /** \addtogroup extensions |
17 | @{ |
18 | */ |
19 | |
20 | #include "foundation/PxMath.h" |
21 | #include "PxPhysXConfig.h" |
22 | #include "common/PxTolerancesScale.h" |
23 | #include "PxJoint.h" |
24 | |
25 | #ifndef PX_DOXYGEN |
26 | namespace physx |
27 | { |
28 | #endif |
29 | |
30 | /** |
31 | \brief Describes the parameters for a joint limit. |
32 | |
33 | Limits are enabled or disabled by setting flags or other configuration parameters joints, see the |
34 | documentation for specific joint types for details. |
35 | |
36 | @see |
37 | */ |
38 | |
39 | class PxJointLimitParameters |
40 | { |
41 | //= ATTENTION! ===================================================================================== |
42 | // Changing the data layout of this class breaks the binary serialization format. See comments for |
43 | // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData |
44 | // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION |
45 | // accordingly. |
46 | //================================================================================================== |
47 | public: |
48 | /** |
49 | \brief Controls the amount of bounce when the joint hits a limit. |
50 | |
51 | A restitution value of 1.0 causes the joint to bounce back with the velocity which it hit the limit. |
52 | A value of zero causes the joint to stop dead. |
53 | |
54 | In situations where the joint has many locked DOFs (e.g. 5) the restitution may not be applied |
55 | correctly. This is due to a limitation in the solver which causes the restitution velocity to become zero |
56 | as the solver enforces constraints on the other DOFs. |
57 | |
58 | This limitation applies to both angular and linear limits, however it is generally most apparent with limited |
59 | angular DOFs. Disabling joint projection and increasing the solver iteration count may improve this behavior |
60 | to some extent. |
61 | |
62 | Also, combining soft joint limits with joint drives driving against those limits may affect stability. |
63 | |
64 | <b>Range:</b> [0,1]<br> |
65 | <b>Default:</b> 0.0 |
66 | */ |
67 | PxReal restitution; |
68 | |
69 | |
70 | /** |
71 | determines the minimum impact velocity which will cause the joint to bounce |
72 | */ |
73 | |
74 | PxReal bounceThreshold; |
75 | /** |
76 | \brief if greater than zero, the limit is soft, i.e. a spring pulls the joint back to the limit |
77 | |
78 | <b>Range:</b> [0, PX_MAX_F32)<br> |
79 | <b>Default:</b> 0.0 |
80 | */ |
81 | PxReal stiffness; |
82 | |
83 | /** |
84 | \brief if spring is greater than zero, this is the damping of the limit spring |
85 | |
86 | <b>Range:</b> [0, PX_MAX_F32)<br> |
87 | <b>Default:</b> 0.0 |
88 | */ |
89 | PxReal damping; |
90 | |
91 | /** |
92 | \brief the distance inside the limit value at which the limit will be considered to be active by the |
93 | solver. As this value is made larger, the limit becomes active more quickly. It thus becomes less |
94 | likely to violate the extents of the limit, but more expensive. |
95 | |
96 | The contact distance should be less than the limit angle or distance, and in the case of a pair limit, |
97 | less than half the distance between the upper and lower bounds. Exceeding this value will result in |
98 | the limit being active all the time. |
99 | |
100 | Making this value too small can result in jitter around the limit. |
101 | |
102 | <b>Default:</b> depends on the joint |
103 | |
104 | @see PxPhysics::getTolerancesScale() |
105 | */ |
106 | |
107 | PxReal contactDistance; |
108 | |
109 | |
110 | |
111 | PxJointLimitParameters() |
112 | : restitution(0) |
113 | , bounceThreshold(0) |
114 | , stiffness(0) |
115 | , damping(0) |
116 | , contactDistance(0) |
117 | { |
118 | } |
119 | |
120 | /** |
121 | \brief Returns true if the current settings are valid. |
122 | |
123 | \return true if the current settings are valid |
124 | */ |
125 | PX_INLINE bool isValid() const |
126 | { |
127 | return PxIsFinite(restitution) && restitution >= 0 && restitution <= 1 && |
128 | PxIsFinite(stiffness) && stiffness >= 0 && |
129 | PxIsFinite(damping) && damping >= 0 && |
130 | PxIsFinite(bounceThreshold) && bounceThreshold >= 0 && |
131 | PxIsFinite(contactDistance) && contactDistance >= 0; |
132 | } |
133 | |
134 | PX_INLINE bool isSoft() const |
135 | { |
136 | return damping>0 || stiffness>0; |
137 | } |
138 | |
139 | protected: |
140 | ~PxJointLimitParameters() {} |
141 | }; |
142 | |
143 | |
144 | /** |
145 | \brief Describes a one-sided linear limit. |
146 | */ |
147 | class PxJointLinearLimit : public PxJointLimitParameters |
148 | { |
149 | //= ATTENTION! ===================================================================================== |
150 | // Changing the data layout of this class breaks the binary serialization format. See comments for |
151 | // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData |
152 | // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION |
153 | // accordingly. |
154 | //================================================================================================== |
155 | public: |
156 | /** |
157 | \brief the extent of the limit. |
158 | |
159 | <b>Range:</b> (0, PX_MAX_F32) <br> |
160 | <b>Default:</b> PX_MAX_F32 |
161 | */ |
162 | PxReal value; |
163 | |
164 | /** |
165 | \brief construct a linear hard limit |
166 | |
167 | \param[in] scale a PxTolerancesScale struct. Should be the same as used when creating the PxPhysics object. |
168 | \param[in] extent the extent of the limit |
169 | \param[in] contactDist the distance from the limit at which it becomes active. Default is 0.01f scaled by the tolerance length scale |
170 | |
171 | @see PxJointLimitParameters PxTolerancesScale |
172 | */ |
173 | |
174 | PxJointLinearLimit(const PxTolerancesScale& scale, PxReal extent, PxReal contactDist = -1) |
175 | : value(extent) |
176 | { |
177 | PxJointLimitParameters::contactDistance = contactDist == -1 ? 0.01f*scale.length : contactDist; |
178 | } |
179 | |
180 | |
181 | /** |
182 | \brief construct a linear soft limit |
183 | |
184 | \param[in] extent the extent of the limit |
185 | \param[in] spring the stiffness and damping parameters for the limit spring |
186 | |
187 | @see PxJointLimitParameters PxTolerancesScale |
188 | */ |
189 | |
190 | PxJointLinearLimit(PxReal extent, const PxSpring& spring) |
191 | : value(extent) |
192 | { |
193 | stiffness = spring.stiffness; |
194 | damping = spring.damping; |
195 | } |
196 | |
197 | |
198 | |
199 | /** |
200 | \brief Returns true if the limit is valid |
201 | |
202 | \return true if the current settings are valid |
203 | */ |
204 | PX_INLINE bool isValid() const |
205 | { |
206 | return PxJointLimitParameters::isValid() && |
207 | PxIsFinite(value) && |
208 | value > 0; |
209 | } |
210 | }; |
211 | |
212 | |
213 | /** |
214 | \brief Describes a two-sided limit. |
215 | */ |
216 | |
217 | class PxJointLinearLimitPair : public PxJointLimitParameters |
218 | { |
219 | //= ATTENTION! ===================================================================================== |
220 | // Changing the data layout of this class breaks the binary serialization format. See comments for |
221 | // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData |
222 | // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION |
223 | // accordingly. |
224 | //================================================================================================== |
225 | public: |
226 | /** |
227 | \brief the range of the limit. The upper limit must be no lower than the |
228 | lower limit, and if they are equal the limited degree of freedom will be treated as locked. |
229 | |
230 | <b>Unit:</b> Angular: Radians |
231 | <b>Range:</b> See the joint on which the limit is used for details<br> |
232 | <b>Default:</b> 0.0 |
233 | */ |
234 | PxReal upper, lower; |
235 | |
236 | |
237 | /** |
238 | \brief Construct a linear hard limit pair. The lower distance value must be less than the upper distance value. |
239 | |
240 | \param[in] scale a PxTolerancesScale struct. Should be the same as used when creating the PxPhysics object. |
241 | \param[in] lowerLimit the lower distance of the limit |
242 | \param[in] upperLimit the upper distance of the limit |
243 | \param[in] contactDist the distance from the limit at which it becomes active. Default is the lesser of 0.01f scaled by the tolerance length scale, and 0.49 * (upperLimit - lowerLimit) |
244 | |
245 | @see PxJointLimitParameters PxTolerancesScale |
246 | */ |
247 | |
248 | PxJointLinearLimitPair(const PxTolerancesScale& scale, PxReal lowerLimit, PxReal upperLimit, PxReal contactDist = -1) |
249 | : upper(upperLimit) |
250 | , lower(lowerLimit) |
251 | { |
252 | PxJointLimitParameters::contactDistance = contactDist == -1 ? PxMin(scale.length * 0.01f, (upperLimit*0.49f-lowerLimit*0.49f)) : contactDist; |
253 | bounceThreshold = 2*scale.length; |
254 | } |
255 | |
256 | |
257 | /** |
258 | \brief construct a linear soft limit pair |
259 | |
260 | \param[in] lowerLimit the lower distance of the limit |
261 | \param[in] upperLimit the upper distance of the limit |
262 | \param[in] spring the stiffness and damping parameters of the limit spring |
263 | |
264 | @see PxJointLimitParameters PxTolerancesScale |
265 | */ |
266 | |
267 | PxJointLinearLimitPair(PxReal lowerLimit, PxReal upperLimit, const PxSpring& spring) |
268 | : upper(upperLimit) |
269 | , lower(lowerLimit) |
270 | { |
271 | stiffness = spring.stiffness; |
272 | damping = spring.damping; |
273 | } |
274 | |
275 | |
276 | /** |
277 | \brief Returns true if the limit is valid. |
278 | |
279 | \return true if the current settings are valid |
280 | */ |
281 | PX_INLINE bool isValid() const |
282 | { |
283 | return PxJointLimitParameters::isValid() && |
284 | PxIsFinite(upper) && PxIsFinite(lower) && upper >= lower && |
285 | PxIsFinite(upper - lower) && |
286 | PxIsFinite(contactDistance) && contactDistance <= upper - lower; |
287 | } |
288 | }; |
289 | |
290 | |
291 | class PxJointAngularLimitPair : public PxJointLimitParameters |
292 | { |
293 | //= ATTENTION! ===================================================================================== |
294 | // Changing the data layout of this class breaks the binary serialization format. See comments for |
295 | // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData |
296 | // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION |
297 | // accordingly. |
298 | //================================================================================================== |
299 | public: |
300 | /** |
301 | \brief the range of the limit. The upper limit must be no lower than the lower limit. |
302 | |
303 | <b>Unit:</b> Angular: Radians |
304 | <b>Range:</b> See the joint on which the limit is used for details<br> |
305 | <b>Default:</b> 0.0 |
306 | */ |
307 | PxReal upper, lower; |
308 | |
309 | |
310 | /** |
311 | \brief construct an angular hard limit pair. |
312 | |
313 | The lower value must be less than the upper value. |
314 | |
315 | \param[in] lowerLimit the lower angle of the limit |
316 | \param[in] upperLimit the upper angle of the limit |
317 | \param[in] contactDist the distance from the limit at which it becomes active. Default is the lesser of 0.1 radians, and 0.49 * (upperLimit - lowerLimit) |
318 | |
319 | @see PxJointLimitParameters |
320 | */ |
321 | |
322 | PxJointAngularLimitPair(PxReal lowerLimit, PxReal upperLimit, PxReal contactDist = -1) |
323 | : upper(upperLimit) |
324 | , lower(lowerLimit) |
325 | { |
326 | PxJointLimitParameters::contactDistance = contactDist ==-1 ? PxMin(0.1f, 0.49f*(upperLimit-lowerLimit)) : contactDist; |
327 | bounceThreshold = 0.5f; |
328 | } |
329 | |
330 | |
331 | /** |
332 | \brief construct an angular soft limit pair. |
333 | |
334 | The lower value must be less than the upper value. |
335 | |
336 | \param[in] lowerLimit the lower angle of the limit |
337 | \param[in] upperLimit the upper angle of the limit |
338 | \param[in] spring the stiffness and damping of the limit spring |
339 | |
340 | @see PxJointLimitParameters |
341 | */ |
342 | |
343 | PxJointAngularLimitPair(PxReal lowerLimit, PxReal upperLimit, const PxSpring& spring) |
344 | : upper(upperLimit) |
345 | , lower(lowerLimit) |
346 | { |
347 | stiffness = spring.stiffness; |
348 | damping = spring.damping; |
349 | } |
350 | |
351 | |
352 | /** |
353 | \brief Returns true if the limit is valid. |
354 | |
355 | \return true if the current settings are valid |
356 | */ |
357 | PX_INLINE bool isValid() const |
358 | { |
359 | return PxJointLimitParameters::isValid() && |
360 | PxIsFinite(upper) && PxIsFinite(lower) && upper >= lower && |
361 | PxIsFinite(contactDistance) && contactDistance <= upper - lower; |
362 | } |
363 | }; |
364 | |
365 | |
366 | |
367 | /** |
368 | \brief Describes an elliptical conical joint limit. Note that very small or highly elliptical limit cones may |
369 | result in jitter. |
370 | |
371 | @see PxD6Joint PxSphericalJoint |
372 | */ |
373 | |
374 | class PxJointLimitCone : public PxJointLimitParameters |
375 | { |
376 | //= ATTENTION! ===================================================================================== |
377 | // Changing the data layout of this class breaks the binary serialization format. See comments for |
378 | // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData |
379 | // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION |
380 | // accordingly. |
381 | //================================================================================================== |
382 | public: |
383 | /** |
384 | \brief the maximum angle from the Y axis of the constraint frame. |
385 | |
386 | <b>Unit:</b> Angular: Radians |
387 | <b>Range:</b> Angular: (0,PI)<br> |
388 | <b>Default:</b> PI/2 |
389 | */ |
390 | PxReal yAngle; |
391 | |
392 | |
393 | /** |
394 | \brief the maximum angle from the Z-axis of the constraint frame. |
395 | |
396 | <b>Unit:</b> Angular: Radians |
397 | <b>Range:</b> Angular: (0,PI)<br> |
398 | <b>Default:</b> PI/2 |
399 | */ |
400 | PxReal zAngle; |
401 | |
402 | /** |
403 | \brief Construct a cone hard limit. |
404 | |
405 | \param[in] yLimitAngle the limit angle from the Y-axis of the constraint frame |
406 | \param[in] zLimitAngle the limit angle from the Z-axis of the constraint frame |
407 | \param[in] contactDist the distance from the limit at which it becomes active. Default is the lesser of 0.1 radians, and 0.49 * the lower of the limit angles |
408 | |
409 | @see PxJointLimitParameters |
410 | */ |
411 | |
412 | PxJointLimitCone(PxReal yLimitAngle, PxReal zLimitAngle, PxReal contactDist = -1): |
413 | yAngle(yLimitAngle), |
414 | zAngle(zLimitAngle) |
415 | { |
416 | PxJointLimitParameters::contactDistance = contactDist == -1 ? PxMin(0.1f, PxMin(yLimitAngle, zLimitAngle)*0.49f) : contactDist; |
417 | bounceThreshold = 0.5f; |
418 | } |
419 | |
420 | |
421 | |
422 | /** |
423 | \brief Construct a cone soft limit. |
424 | |
425 | \param[in] yLimitAngle the limit angle from the Y-axis of the constraint frame |
426 | \param[in] zLimitAngle the limit angle from the Z-axis of the constraint frame |
427 | \param[in] spring the stiffness and damping of the limit spring |
428 | |
429 | @see PxJointLimitParameters |
430 | */ |
431 | |
432 | PxJointLimitCone(PxReal yLimitAngle, PxReal zLimitAngle, const PxSpring& spring): |
433 | yAngle(yLimitAngle), |
434 | zAngle(zLimitAngle) |
435 | { |
436 | stiffness = spring.stiffness; |
437 | damping = spring.damping; |
438 | } |
439 | |
440 | |
441 | /** |
442 | \brief Returns true if the limit is valid. |
443 | |
444 | \return true if the current settings are valid |
445 | */ |
446 | PX_INLINE bool isValid() const |
447 | { |
448 | return PxJointLimitParameters::isValid() && |
449 | PxIsFinite(yAngle) && yAngle>0 && yAngle<PxPi && |
450 | PxIsFinite(zAngle) && zAngle>0 && zAngle<PxPi; |
451 | } |
452 | }; |
453 | |
454 | #ifndef PX_DOXYGEN |
455 | } // namespace physx |
456 | #endif |
457 | |
458 | /** @} */ |
459 | #endif |
460 | |