1 | // |
2 | // Redistribution and use in source and binary forms, with or without |
3 | // modification, are permitted provided that the following conditions |
4 | // are met: |
5 | // * Redistributions of source code must retain the above copyright |
6 | // notice, this list of conditions and the following disclaimer. |
7 | // * Redistributions in binary form must reproduce the above copyright |
8 | // notice, this list of conditions and the following disclaimer in the |
9 | // documentation and/or other materials provided with the distribution. |
10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
11 | // contributors may be used to endorse or promote products derived |
12 | // from this software without specific prior written permission. |
13 | // |
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | // |
26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
29 | |
30 | #ifndef PX_PHYSICS_NX_CONSTRAINTDESC |
31 | #define PX_PHYSICS_NX_CONSTRAINTDESC |
32 | |
33 | /** \addtogroup physics |
34 | @{ |
35 | */ |
36 | |
37 | #include "PxPhysXConfig.h" |
38 | #include "foundation/PxFlags.h" |
39 | #include "foundation/PxVec3.h" |
40 | #include "common/PxBase.h" |
41 | |
42 | #if !PX_DOXYGEN |
43 | namespace physx { namespace pvdsdk { |
44 | #endif |
45 | class PvdDataStream; |
46 | #if !PX_DOXYGEN |
47 | }} |
48 | #endif |
49 | |
50 | #if !PX_DOXYGEN |
51 | namespace physx |
52 | { |
53 | #endif |
54 | |
55 | class PxConstraintConnector; |
56 | class PxRigidActor; |
57 | class PxScene; |
58 | class PxConstraintConnector; |
59 | class PxRenderBuffer; |
60 | class PxDeletionListener; |
61 | |
62 | /** |
63 | \brief constraint row flags |
64 | |
65 | These flags configure the post-processing of constraint rows and the behavior of the solver while solving constraints |
66 | */ |
67 | struct Px1DConstraintFlag |
68 | { |
69 | PX_CUDA_CALLABLE Px1DConstraintFlag(){} |
70 | |
71 | enum Type |
72 | { |
73 | eSPRING = 1<<0, //!< whether the constraint is a spring. Mutually exclusive with eRESTITUTION. If set, eKEEPBIAS is ignored. |
74 | eACCELERATION_SPRING = 1<<1, //!< whether the constraint is a force or acceleration spring. Only valid if eSPRING is set. |
75 | eRESTITUTION = 1<<2, //!< whether the restitution model should be applied to generate the target velocity. Mutually exclusive with eSPRING. If restitution causes a bounces, eKEEPBIAS is ignored |
76 | eKEEPBIAS = 1<<3, //!< whether to keep the error term when solving for velocity. Ignored if restitution generates bounce, or eSPRING is set. |
77 | eOUTPUT_FORCE = 1<<4, //!< whether to accumulate the force value from this constraint in the force total that is reported for the constraint and tested for breakage |
78 | eHAS_DRIVE_LIMIT = 1<<5, //!< whether the constraint has a drive force limit (which will be scaled by dt unless PxConstraintFlag::eLIMITS_ARE_FORCES is set) |
79 | eANGULAR_CONSTRAINT = 1 << 6,//!< Whether this is an angular or linear constraint |
80 | eDRIVE_ROW = 1 << 7 |
81 | }; |
82 | }; |
83 | |
84 | typedef PxFlags<Px1DConstraintFlag::Type, PxU16> Px1DConstraintFlags; |
85 | PX_FLAGS_OPERATORS(Px1DConstraintFlag::Type, PxU16) |
86 | |
87 | /** |
88 | \brief constraint type hints which the solver uses to optimize constraint handling |
89 | */ |
90 | struct PxConstraintSolveHint |
91 | { |
92 | enum Enum |
93 | { |
94 | eNONE = 0, //!< no special properties |
95 | eACCELERATION1 = 256, //!< a group of acceleration drive constraints with the same stiffness and drive parameters |
96 | eSLERP_SPRING = 258, //!< temporary special value to identify SLERP drive rows |
97 | eACCELERATION2 = 512, //!< a group of acceleration drive constraints with the same stiffness and drive parameters |
98 | eACCELERATION3 = 768, //!< a group of acceleration drive constraints with the same stiffness and drive parameters |
99 | eROTATIONAL_EQUALITY = 1024, //!< rotational equality constraints with no force limit and no velocity target |
100 | eROTATIONAL_INEQUALITY = 1025, //!< rotational inequality constraints with (0, PX_MAX_FLT) force limits |
101 | eEQUALITY = 2048, //!< equality constraints with no force limit and no velocity target |
102 | eINEQUALITY = 2049 //!< inequality constraints with (0, PX_MAX_FLT) force limits |
103 | }; |
104 | }; |
105 | |
106 | /** |
107 | \brief A constraint |
108 | |
109 | A constraint is expressed as a set of 1-dimensional constraint rows which define the required constraint |
110 | on the objects' velocities. |
111 | |
112 | Each constraint is either a hard constraint or a spring. We define the velocity at the constraint to be |
113 | the quantity |
114 | |
115 | v = body0vel.dot(lin0,ang0) - body1vel.dot(lin1, ang1) |
116 | |
117 | For a hard constraint, the solver attempts to generate |
118 | |
119 | 1. a set of velocities for the objects which, when integrated, respect the constraint errors: |
120 | |
121 | v + (geometricError / timestep) = velocityTarget |
122 | |
123 | 2. a set of velocities for the objects which respect the constraints: |
124 | |
125 | v = velocityTarget |
126 | |
127 | Hard constraints support restitution: if the impact velocity exceeds the bounce threshold, then the target velocity |
128 | of the constraint will be set to restitution * -v |
129 | |
130 | Alternatively, the solver can attempt to resolve the velocity constraint as an implicit spring: |
131 | |
132 | F = stiffness * -geometricError + damping * (velocityTarget - v) |
133 | |
134 | where F is the constraint force or acceleration. Springs are fully implicit: that is, the force or acceleration |
135 | is a function of the position and velocity after the solve. |
136 | |
137 | All constraints support limits on the minimum or maximum impulse applied. |
138 | */ |
139 | |
140 | PX_ALIGN_PREFIX(16) |
141 | struct Px1DConstraint |
142 | { |
143 | PxVec3 linear0; //!< linear component of velocity jacobian in world space |
144 | PxReal geometricError; //!< geometric error of the constraint along this axis |
145 | PxVec3 angular0; //!< angular component of velocity jacobian in world space |
146 | PxReal velocityTarget; //!< velocity target for the constraint along this axis |
147 | |
148 | PxVec3 linear1; //!< linear component of velocity jacobian in world space |
149 | PxReal minImpulse; //!< minimum impulse the solver may apply to enforce this constraint |
150 | PxVec3 angular1; //!< angular component of velocity jacobian in world space |
151 | PxReal maxImpulse; //!< maximum impulse the solver may apply to enforce this constraint |
152 | |
153 | union |
154 | { |
155 | struct SpringModifiers |
156 | { |
157 | PxReal stiffness; //!< spring parameter, for spring constraints |
158 | PxReal damping; //!< damping parameter, for spring constraints |
159 | } spring; |
160 | struct RestitutionModifiers |
161 | { |
162 | PxReal restitution; //!< restitution parameter for determining additional "bounce" |
163 | PxReal velocityThreshold; //!< minimum impact velocity for bounce |
164 | } bounce; |
165 | } mods; |
166 | |
167 | PxReal forInternalUse; //!< for internal use only |
168 | PxU16 flags; //!< a set of Px1DConstraintFlags |
169 | PxU16 solveHint; //!< constraint optimization hint, should be an element of PxConstraintSolveHint |
170 | } |
171 | PX_ALIGN_SUFFIX(16); |
172 | |
173 | |
174 | /** |
175 | \brief Flags for determining which components of the constraint should be visualized. |
176 | |
177 | @see PxConstraintVisualize |
178 | */ |
179 | struct PxConstraintVisualizationFlag |
180 | { |
181 | enum Enum |
182 | { |
183 | eLOCAL_FRAMES = 1, //!< visualize constraint frames |
184 | eLIMITS = 2 //!< visualize constraint limits |
185 | }; |
186 | }; |
187 | |
188 | PX_ALIGN_PREFIX(16) |
189 | struct PxConstraintInvMassScale |
190 | { |
191 | //= ATTENTION! ===================================================================================== |
192 | // Changing the data layout of this class breaks the binary serialization format. See comments for |
193 | // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData |
194 | // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION |
195 | // accordingly. |
196 | //================================================================================================== |
197 | |
198 | PxReal linear0; //!< multiplier for inverse mass of body0 |
199 | PxReal angular0; //!< multiplier for inverse MoI of body0 |
200 | PxReal linear1; //!< multiplier for inverse mass of body1 |
201 | PxReal angular1; //!< multiplier for inverse MoI of body1 |
202 | |
203 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxConstraintInvMassScale(){} |
204 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxConstraintInvMassScale(PxReal lin0, PxReal ang0, PxReal lin1, PxReal ang1) : linear0(lin0), angular0(ang0), linear1(lin1), angular1(ang1){} |
205 | } |
206 | PX_ALIGN_SUFFIX(16); |
207 | |
208 | /** solver constraint generation shader |
209 | |
210 | This function is called by the constraint solver framework. The function must be reentrant, since it may be called simultaneously |
211 | from multiple threads, and should access only the arguments passed into it. |
212 | |
213 | Developers writing custom constraints are encouraged to read the documentation in the user guide and the implementation code in PhysXExtensions. |
214 | |
215 | \param[out] constraints An array of solver constraint rows to be filled in |
216 | \param[out] bodyAWorldOffset The origin point (offset from the position vector of bodyA's center of mass) at which the constraint is resolved. This value does not affect how constraints are solved, only the constraint force reported. |
217 | \param[in] maxConstraints The size of the constraint buffer. At most this many constraints rows may be written |
218 | \param[out] invMassScale The inverse mass and inertia scales for the constraint |
219 | \param[in] constantBlock The constant data block |
220 | \param[in] bodyAToWorld The center of mass frame of the first constrained body (the identity transform if the first actor is static, or if a NULL actor pointer was provided for it) |
221 | \param[in] bodyBToWorld The center of mass frame of the second constrained body (the identity transform if the second actor is static, or if a NULL actor pointer was provided for it) |
222 | \param[in] useExtendedLimits Enables limit ranges outside of (-PI, PI) |
223 | \param[out] cAtW The world space location of body A's joint frame (position only) |
224 | \param[out] cBtW The world space location of body B's joint frame (position only) |
225 | |
226 | \return the number of constraint rows written. |
227 | */ |
228 | typedef PxU32 (*PxConstraintSolverPrep)(Px1DConstraint* constraints, |
229 | PxVec3& bodyAWorldOffset, |
230 | PxU32 maxConstraints, |
231 | PxConstraintInvMassScale& invMassScale, |
232 | const void* constantBlock, |
233 | const PxTransform& bodyAToWorld, |
234 | const PxTransform& bodyBToWorld, |
235 | bool useExtendedLimits, |
236 | PxVec3& cAtW, |
237 | PxVec3& cBtW); |
238 | |
239 | /** solver constraint projection shader |
240 | |
241 | This function is called by the constraint post-solver framework. The function must be reentrant, since it may be called simultaneously |
242 | from multiple threads and should access only the arguments passed into it. |
243 | |
244 | \param[in] constantBlock The constant data block |
245 | \param[out] bodyAToWorld The center of mass frame of the first constrained body (the identity if the actor is static or a NULL pointer was provided for it) |
246 | \param[out] bodyBToWorld The center of mass frame of the second constrained body (the identity if the actor is static or a NULL pointer was provided for it) |
247 | \param[in] projectToA True if the constraint should be projected by moving the second body towards the first, false if the converse |
248 | */ |
249 | typedef void (*PxConstraintProject)(const void* constantBlock, |
250 | PxTransform& bodyAToWorld, |
251 | PxTransform& bodyBToWorld, |
252 | bool projectToA); |
253 | |
254 | /** |
255 | API used to visualize details about a constraint. |
256 | */ |
257 | class PxConstraintVisualizer |
258 | { |
259 | protected: |
260 | virtual ~PxConstraintVisualizer(){} |
261 | public: |
262 | /** Visualize joint frames |
263 | |
264 | \param[in] parent Parent transformation |
265 | \param[in] child Child transformation |
266 | */ |
267 | virtual void visualizeJointFrames(const PxTransform& parent, const PxTransform& child) = 0; |
268 | |
269 | /** Visualize joint linear limit |
270 | |
271 | \param[in] t0 Base transformation |
272 | \param[in] t1 End transformation |
273 | \param[in] value Distance |
274 | \param[in] active State of the joint - active/inactive |
275 | */ |
276 | virtual void visualizeLinearLimit(const PxTransform& t0, const PxTransform& t1, PxReal value, bool active) = 0; |
277 | |
278 | /** Visualize joint angular limit |
279 | |
280 | \param[in] t0 Transformation for the visualization |
281 | \param[in] lower Lower limit angle |
282 | \param[in] upper Upper limit angle |
283 | \param[in] active State of the joint - active/inactive |
284 | */ |
285 | virtual void visualizeAngularLimit(const PxTransform& t0, PxReal lower, PxReal upper, bool active) = 0; |
286 | |
287 | /** Visualize limit cone |
288 | |
289 | \param[in] t Transformation for the visualization |
290 | \param[in] tanQSwingY Tangent of the quarter Y angle |
291 | \param[in] tanQSwingZ Tangent of the quarter Z angle |
292 | \param[in] active State of the joint - active/inactive |
293 | */ |
294 | virtual void visualizeLimitCone(const PxTransform& t, PxReal tanQSwingY, PxReal tanQSwingZ, bool active) = 0; |
295 | |
296 | /** Visualize joint double cone |
297 | |
298 | \param[in] t Transformation for the visualization |
299 | \param[in] angle Limit angle |
300 | \param[in] active State of the joint - active/inactive |
301 | */ |
302 | virtual void visualizeDoubleCone(const PxTransform& t, PxReal angle, bool active) = 0; |
303 | |
304 | /** Visualize line |
305 | |
306 | \param[in] p0 Start position |
307 | \param[in] p1 End postion |
308 | \param[in] color Color |
309 | */ |
310 | virtual void visualizeLine(const PxVec3& p0, const PxVec3& p1, PxU32 color) = 0; |
311 | }; |
312 | |
313 | /** solver constraint visualization function |
314 | |
315 | This function is called by the constraint post-solver framework to visualize the constraint |
316 | |
317 | \param[out] visualizer The render buffer to render to |
318 | \param[in] constantBlock The constant data block |
319 | \param[in] body0Transform The center of mass frame of the first constrained body (the identity if the actor is static, or a NULL pointer was provided for it) |
320 | \param[in] body1Transform The center of mass frame of the second constrained body (the identity if the actor is static, or a NULL pointer was provided for it) |
321 | \param[in] flags The visualization flags (PxConstraintVisualizationFlag) |
322 | |
323 | @see PxRenderBuffer |
324 | */ |
325 | typedef void (*PxConstraintVisualize)(PxConstraintVisualizer& visualizer, |
326 | const void* constantBlock, |
327 | const PxTransform& body0Transform, |
328 | const PxTransform& body1Transform, |
329 | PxU32 flags); |
330 | |
331 | |
332 | struct PxPvdUpdateType |
333 | { |
334 | enum Enum |
335 | { |
336 | CREATE_INSTANCE, |
337 | RELEASE_INSTANCE, |
338 | UPDATE_ALL_PROPERTIES, |
339 | UPDATE_SIM_PROPERTIES |
340 | }; |
341 | }; |
342 | |
343 | /** |
344 | |
345 | \brief This class connects a custom constraint to the SDK |
346 | |
347 | This class connects a custom constraint to the SDK, and functions are called by the SDK |
348 | to query the custom implementation for specific information to pass on to the application |
349 | or inform the constraint when the application makes calls into the SDK which will update |
350 | the custom constraint's internal implementation |
351 | */ |
352 | class PxConstraintConnector |
353 | { |
354 | public: |
355 | /** |
356 | when the constraint is marked dirty, this function is called at the start of the simulation |
357 | step for the SDK to copy the constraint data block. |
358 | */ |
359 | virtual void* prepareData() = 0; |
360 | |
361 | /** |
362 | this function is called by the SDK to update PVD's view of it |
363 | */ |
364 | virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream& pvdConnection, |
365 | const PxConstraint* c, |
366 | PxPvdUpdateType::Enum updateType) const = 0; |
367 | |
368 | /** |
369 | When the SDK deletes a PxConstraint object this function is called by the SDK. In general |
370 | custom constraints should not be deleted directly by applications: rather, the constraint |
371 | should respond to a release() request by calling PxConstraint::release(), then wait for |
372 | this call to release its own resources, so that even if the release() call occurs during |
373 | a simulation step, the deletion of the constraint is buffered until that step completes. |
374 | |
375 | This function is also called when a PxConstraint object is deleted on cleanup due to |
376 | destruction of the PxPhysics object. |
377 | */ |
378 | virtual void onConstraintRelease() = 0; |
379 | |
380 | /** |
381 | This function is called by the SDK when the CoM of one of the actors is moved. Since the |
382 | API specifies constraint positions relative to actors, and the constraint shader functions |
383 | are supplied with coordinates relative to bodies, some synchronization is usually required |
384 | when the application moves an object's center of mass. |
385 | */ |
386 | virtual void onComShift(PxU32 actor) = 0; |
387 | |
388 | /** |
389 | This function is called by the SDK when the scene origin gets shifted and allows to adjust |
390 | custom data which contains world space transforms. |
391 | |
392 | \note If the adjustments affect constraint shader data, it is necessary to call PxConstraint::markDirty() |
393 | to make sure that the data gets synced at the beginning of the next simulation step. |
394 | |
395 | \param[in] shift Translation vector the origin is shifted by. |
396 | |
397 | @see PxScene.shiftOrigin() |
398 | */ |
399 | virtual void onOriginShift(const PxVec3& shift) = 0; |
400 | |
401 | /** |
402 | \brief Fetches external data for a constraint. |
403 | |
404 | This function is used by the SDK to acquire a reference to the owner of a constraint and a unique |
405 | owner type ID. This information will be passed on when a breakable constraint breaks or when |
406 | #PxConstraint::getExternalReference() is called. |
407 | |
408 | \param[out] typeID Unique type identifier of the external object. The value 0xffffffff is reserved and should not be used. Furthermore, if the PhysX extensions library is used, some other IDs are reserved already (see PxConstraintExtIDs) |
409 | \return Reference to the external object which owns the constraint. |
410 | |
411 | @see PxConstraintInfo PxSimulationEventCallback.onConstraintBreak() |
412 | */ |
413 | virtual void* getExternalReference(PxU32& typeID) = 0; |
414 | |
415 | /** |
416 | \brief Obtain a reference to a PxBase interface if the constraint has one. |
417 | |
418 | If the constraint does not implement the PxBase interface, it should return NULL. |
419 | */ |
420 | virtual PxBase* getSerializable() = 0; |
421 | |
422 | /** |
423 | \brief Obtain the shader function pointer used to prep rows for this constraint |
424 | */ |
425 | virtual PxConstraintSolverPrep getPrep() const = 0; |
426 | |
427 | /** |
428 | \brief Obtain the pointer to the constraint's constant data |
429 | */ |
430 | virtual const void* getConstantBlock() const = 0; |
431 | |
432 | /** |
433 | \brief virtual destructor |
434 | */ |
435 | virtual ~PxConstraintConnector() {} |
436 | }; |
437 | |
438 | #if !PX_DOXYGEN |
439 | } // namespace physx |
440 | #endif |
441 | |
442 | /** @} */ |
443 | #endif |
444 | |