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 | |
31 | #include "NpRigidDynamic.h" |
32 | #include "NpRigidActorTemplateInternal.h" |
33 | |
34 | using namespace physx; |
35 | |
36 | NpRigidDynamic::NpRigidDynamic(const PxTransform& bodyPose) |
37 | : NpRigidDynamicT(PxConcreteType::eRIGID_DYNAMIC, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE, PxActorType::eRIGID_DYNAMIC, bodyPose) |
38 | {} |
39 | |
40 | NpRigidDynamic::~NpRigidDynamic() |
41 | { |
42 | } |
43 | |
44 | // PX_SERIALIZATION |
45 | void NpRigidDynamic::requiresObjects(PxProcessPxBaseCallback& c) |
46 | { |
47 | NpRigidDynamicT::requiresObjects(c); |
48 | } |
49 | |
50 | void NpRigidDynamic::preExportDataReset() |
51 | { |
52 | NpRigidDynamicT::preExportDataReset(); |
53 | if (isKinematic() && NpActor::getAPIScene(actor: *this)) |
54 | { |
55 | //Restore dynamic data in case the actor is configured as a kinematic. |
56 | //otherwise we would loose the data for switching the kinematic actor back to dynamic |
57 | //after deserialization. |
58 | getScbBodyFast().getScBody().restoreDynamicData(); |
59 | } |
60 | } |
61 | |
62 | NpRigidDynamic* NpRigidDynamic::createObject(PxU8*& address, PxDeserializationContext& context) |
63 | { |
64 | NpRigidDynamic* obj = new (address) NpRigidDynamic(PxBaseFlag::eIS_RELEASABLE); |
65 | address += sizeof(NpRigidDynamic); |
66 | obj->importExtraData(context); |
67 | obj->resolveReferences(context); |
68 | return obj; |
69 | } |
70 | //~PX_SERIALIZATION |
71 | |
72 | void NpRigidDynamic::release() |
73 | { |
74 | releaseActorT(actor: this, scbActor&: mBody); |
75 | } |
76 | |
77 | |
78 | void NpRigidDynamic::setGlobalPose(const PxTransform& pose, bool autowake) |
79 | { |
80 | NpScene* scene = NpActor::getAPIScene(actor: *this); |
81 | |
82 | #if PX_CHECKED |
83 | if(scene) |
84 | scene->checkPositionSanity(*this, pose, "PxRigidDynamic::setGlobalPose" ); |
85 | #endif |
86 | |
87 | PX_CHECK_AND_RETURN(pose.isSane(), "PxRigidDynamic::setGlobalPose: pose is not valid." ); |
88 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
89 | |
90 | const PxTransform newPose = pose.getNormalized(); //AM: added to fix 1461 where users read and write orientations for no reason. |
91 | |
92 | Scb::Body& b = getScbBodyFast(); |
93 | const PxTransform body2World = newPose * b.getBody2Actor(); |
94 | b.setBody2World(p: body2World, asPartOfBody2ActorChange: false); |
95 | |
96 | if(scene) |
97 | updateDynamicSceneQueryShapes(shapeManager&: mShapeManager, sqManager&: scene->getSceneQueryManagerFast(), actor: *this); |
98 | |
99 | // invalidate the pruning structure if the actor bounds changed |
100 | if(mShapeManager.getPruningStructure()) |
101 | { |
102 | Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, messageFmt: "PxRigidDynamic::setGlobalPose: Actor is part of a pruning structure, pruning structure is now invalid!" ); |
103 | mShapeManager.getPruningStructure()->invalidate(actor: this); |
104 | } |
105 | |
106 | if(scene && autowake && !(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)) |
107 | wakeUpInternal(); |
108 | } |
109 | |
110 | |
111 | PX_FORCE_INLINE void NpRigidDynamic::setKinematicTargetInternal(const PxTransform& targetPose) |
112 | { |
113 | Scb::Body& b = getScbBodyFast(); |
114 | |
115 | // The target is actor related. Transform to body related target |
116 | const PxTransform bodyTarget = targetPose * b.getBody2Actor(); |
117 | |
118 | b.setKinematicTarget(bodyTarget); |
119 | |
120 | NpScene* scene = NpActor::getAPIScene(actor: *this); |
121 | if ((b.getFlags() & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES) && scene) |
122 | { |
123 | updateDynamicSceneQueryShapes(shapeManager&: mShapeManager, sqManager&: scene->getSceneQueryManagerFast(), actor: *this); |
124 | } |
125 | } |
126 | |
127 | |
128 | void NpRigidDynamic::setKinematicTarget(const PxTransform& destination) |
129 | { |
130 | PX_CHECK_AND_RETURN(destination.isSane(), "PxRigidDynamic::setKinematicTarget: destination is not valid." ); |
131 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
132 | |
133 | #if PX_CHECKED |
134 | NpScene* scene = NpActor::getAPIScene(*this); |
135 | if(scene) |
136 | scene->checkPositionSanity(*this, destination, "PxRigidDynamic::setKinematicTarget" ); |
137 | |
138 | Scb::Body& b = getScbBodyFast(); |
139 | PX_CHECK_AND_RETURN((b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setKinematicTarget: Body must be kinematic!" ); |
140 | PX_CHECK_AND_RETURN(scene, "PxRigidDynamic::setKinematicTarget: Body must be in a scene!" ); |
141 | PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setKinematicTarget: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
142 | #endif |
143 | |
144 | setKinematicTargetInternal(destination.getNormalized()); |
145 | } |
146 | |
147 | |
148 | bool NpRigidDynamic::getKinematicTarget(PxTransform& target) const |
149 | { |
150 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
151 | |
152 | const Scb::Body& b = getScbBodyFast(); |
153 | if(b.getFlags() & PxRigidBodyFlag::eKINEMATIC) |
154 | { |
155 | PxTransform bodyTarget; |
156 | if(b.getKinematicTarget(p&: bodyTarget)) |
157 | { |
158 | // The internal target is body related. Transform to actor related target |
159 | target = bodyTarget * b.getBody2Actor().getInverse(); |
160 | return true; |
161 | } |
162 | } |
163 | return false; |
164 | } |
165 | |
166 | void NpRigidDynamic::setCMassLocalPose(const PxTransform& pose) |
167 | { |
168 | PX_CHECK_AND_RETURN(pose.isSane(), "PxRigidDynamic::setCMassLocalPose pose is not valid." ); |
169 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
170 | |
171 | const PxTransform p = pose.getNormalized(); |
172 | |
173 | const PxTransform oldBody2Actor = getScbBodyFast().getBody2Actor(); |
174 | |
175 | NpRigidDynamicT::setCMassLocalPoseInternal(p); |
176 | |
177 | Scb::Body& b = getScbBodyFast(); |
178 | if(b.getFlags() & PxRigidBodyFlag::eKINEMATIC) |
179 | { |
180 | PxTransform bodyTarget; |
181 | if(b.getKinematicTarget(p&: bodyTarget)) |
182 | { |
183 | PxTransform actorTarget = bodyTarget * oldBody2Actor.getInverse(); // get old target pose for the actor from the body target |
184 | setKinematicTargetInternal(actorTarget); |
185 | } |
186 | } |
187 | } |
188 | |
189 | |
190 | void NpRigidDynamic::setLinearDamping(PxReal linearDamping) |
191 | { |
192 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
193 | PX_CHECK_AND_RETURN(PxIsFinite(linearDamping), "PxRigidDynamic::setLinearDamping: invalid float" ); |
194 | PX_CHECK_AND_RETURN(linearDamping >=0, "PxRigidDynamic::setLinearDamping: The linear damping must be nonnegative!" ); |
195 | |
196 | getScbBodyFast().setLinearDamping(linearDamping); |
197 | } |
198 | |
199 | |
200 | PxReal NpRigidDynamic::getLinearDamping() const |
201 | { |
202 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
203 | |
204 | return getScbBodyFast().getLinearDamping(); |
205 | } |
206 | |
207 | |
208 | void NpRigidDynamic::setAngularDamping(PxReal angularDamping) |
209 | { |
210 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
211 | PX_CHECK_AND_RETURN(PxIsFinite(angularDamping), "PxRigidDynamic::setAngularDamping: invalid float" ); |
212 | PX_CHECK_AND_RETURN(angularDamping>=0, "PxRigidDynamic::setAngularDamping: The angular damping must be nonnegative!" ) |
213 | |
214 | getScbBodyFast().setAngularDamping(angularDamping); |
215 | } |
216 | |
217 | |
218 | PxReal NpRigidDynamic::getAngularDamping() const |
219 | { |
220 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
221 | |
222 | return getScbBodyFast().getAngularDamping(); |
223 | } |
224 | |
225 | |
226 | void NpRigidDynamic::setLinearVelocity(const PxVec3& velocity, bool autowake) |
227 | { |
228 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
229 | PX_CHECK_AND_RETURN(velocity.isFinite(), "PxRigidDynamic::setLinearVelocity: velocity is not valid." ); |
230 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setLinearVelocity: Body must be non-kinematic!" ); |
231 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setLinearVelocity: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
232 | |
233 | Scb::Body& b = getScbBodyFast(); |
234 | b.setLinearVelocity(velocity); |
235 | |
236 | NpScene* scene = NpActor::getAPIScene(actor: *this); |
237 | if(scene) |
238 | wakeUpInternalNoKinematicTest(body&: b, forceWakeUp: (!velocity.isZero()), autowake); |
239 | } |
240 | |
241 | |
242 | void NpRigidDynamic::setAngularVelocity(const PxVec3& velocity, bool autowake) |
243 | { |
244 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
245 | PX_CHECK_AND_RETURN(velocity.isFinite(), "PxRigidDynamic::setAngularVelocity: velocity is not valid." ); |
246 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setAngularVelocity: Body must be non-kinematic!" ); |
247 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setAngularVelocity: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
248 | |
249 | Scb::Body& b = getScbBodyFast(); |
250 | b.setAngularVelocity(velocity); |
251 | |
252 | NpScene* scene = NpActor::getAPIScene(actor: *this); |
253 | if(scene) |
254 | wakeUpInternalNoKinematicTest(body&: b, forceWakeUp: (!velocity.isZero()), autowake); |
255 | } |
256 | |
257 | |
258 | void NpRigidDynamic::setMaxAngularVelocity(PxReal maxAngularVelocity) |
259 | { |
260 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
261 | PX_CHECK_AND_RETURN(PxIsFinite(maxAngularVelocity), "PxRigidDynamic::setMaxAngularVelocity: invalid float" ); |
262 | PX_CHECK_AND_RETURN(maxAngularVelocity>=0.0f, "PxRigidDynamic::setMaxAngularVelocity: threshold must be non-negative!" ); |
263 | |
264 | getScbBodyFast().setMaxAngVelSq(maxAngularVelocity * maxAngularVelocity); |
265 | } |
266 | |
267 | |
268 | PxReal NpRigidDynamic::getMaxAngularVelocity() const |
269 | { |
270 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
271 | |
272 | return PxSqrt(a: getScbBodyFast().getMaxAngVelSq()); |
273 | } |
274 | |
275 | void NpRigidDynamic::setMaxLinearVelocity(PxReal maxLinearVelocity) |
276 | { |
277 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
278 | PX_CHECK_AND_RETURN(PxIsFinite(maxLinearVelocity), "PxRigidDynamic::setMaxAngularVelocity: invalid float" ); |
279 | PX_CHECK_AND_RETURN(maxLinearVelocity >= 0.0f, "PxRigidDynamic::setMaxAngularVelocity: threshold must be non-negative!" ); |
280 | |
281 | getScbBodyFast().setMaxLinVelSq(maxLinearVelocity * maxLinearVelocity); |
282 | } |
283 | |
284 | PxReal NpRigidDynamic::getMaxLinearVelocity() const |
285 | { |
286 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
287 | |
288 | return PxSqrt(a: getScbBodyFast().getMaxLinVelSq()); |
289 | } |
290 | |
291 | |
292 | void NpRigidDynamic::addForce(const PxVec3& force, PxForceMode::Enum mode, bool autowake) |
293 | { |
294 | Scb::Body& b = getScbBodyFast(); |
295 | |
296 | PX_CHECK_AND_RETURN(force.isFinite(), "PxRigidDynamic::addForce: force is not valid." ); |
297 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
298 | PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::addForce: Body must be in a scene!" ); |
299 | PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::addForce: Body must be non-kinematic!" ); |
300 | PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::addForce: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
301 | |
302 | addSpatialForce(force: &force, NULL, mode); |
303 | |
304 | wakeUpInternalNoKinematicTest(body&: b, forceWakeUp: (!force.isZero()), autowake); |
305 | } |
306 | |
307 | void NpRigidDynamic::setForceAndTorque(const PxVec3& force, const PxVec3& torque, PxForceMode::Enum mode) |
308 | { |
309 | Scb::Body& b = getScbBodyFast(); |
310 | |
311 | PX_CHECK_AND_RETURN(force.isFinite(), "PxRigidDynamic::setForce: force is not valid." ); |
312 | PX_CHECK_AND_RETURN(torque.isFinite(), "PxRigidDynamic::setForce: force is not valid." ); |
313 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
314 | PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::addForce: Body must be in a scene!" ); |
315 | PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::addForce: Body must be non-kinematic!" ); |
316 | PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::addForce: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
317 | |
318 | setSpatialForce(force: &force, torque: &torque, mode); |
319 | |
320 | wakeUpInternalNoKinematicTest(body&: b, forceWakeUp: (!force.isZero()), autowake: true); |
321 | } |
322 | |
323 | |
324 | void NpRigidDynamic::addTorque(const PxVec3& torque, PxForceMode::Enum mode, bool autowake) |
325 | { |
326 | Scb::Body& b = getScbBodyFast(); |
327 | |
328 | PX_CHECK_AND_RETURN(torque.isFinite(), "PxRigidDynamic::addTorque: torque is not valid." ); |
329 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
330 | PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::addTorque: Body must be in a scene!" ); |
331 | PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::addTorque: Body must be non-kinematic!" ); |
332 | PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::addTorque: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
333 | |
334 | addSpatialForce(NULL, torque: &torque, mode); |
335 | |
336 | wakeUpInternalNoKinematicTest(body&: b, forceWakeUp: (!torque.isZero()), autowake); |
337 | } |
338 | |
339 | void NpRigidDynamic::clearForce(PxForceMode::Enum mode) |
340 | { |
341 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
342 | PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::clearForce: Body must be in a scene!" ); |
343 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::clearForce: Body must be non-kinematic!" ); |
344 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::clearForce: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
345 | |
346 | clearSpatialForce(mode, force: true, torque: false); |
347 | } |
348 | |
349 | |
350 | void NpRigidDynamic::clearTorque(PxForceMode::Enum mode) |
351 | { |
352 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
353 | PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::clearTorque: Body must be in a scene!" ); |
354 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::clearTorque: Body must be non-kinematic!" ); |
355 | PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::clearTorque: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
356 | |
357 | clearSpatialForce(mode, force: false, torque: true); |
358 | } |
359 | |
360 | |
361 | bool NpRigidDynamic::isSleeping() const |
362 | { |
363 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
364 | PX_CHECK_AND_RETURN_VAL(NpActor::getAPIScene(*this), "PxRigidDynamic::isSleeping: Body must be in a scene." , true); |
365 | |
366 | return getScbBodyFast().isSleeping(); |
367 | } |
368 | |
369 | |
370 | void NpRigidDynamic::setSleepThreshold(PxReal threshold) |
371 | { |
372 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
373 | PX_CHECK_AND_RETURN(PxIsFinite(threshold), "PxRigidDynamic::setSleepThreshold: invalid float." ); |
374 | PX_CHECK_AND_RETURN(threshold>=0.0f, "PxRigidDynamic::setSleepThreshold: threshold must be non-negative!" ); |
375 | |
376 | getScbBodyFast().setSleepThreshold(threshold); |
377 | } |
378 | |
379 | |
380 | PxReal NpRigidDynamic::getSleepThreshold() const |
381 | { |
382 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
383 | |
384 | return getScbBodyFast().getSleepThreshold(); |
385 | } |
386 | |
387 | void NpRigidDynamic::setStabilizationThreshold(PxReal threshold) |
388 | { |
389 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
390 | PX_CHECK_AND_RETURN(PxIsFinite(threshold), "PxRigidDynamic::setSleepThreshold: invalid float." ); |
391 | PX_CHECK_AND_RETURN(threshold>=0.0f, "PxRigidDynamic::setSleepThreshold: threshold must be non-negative!" ); |
392 | |
393 | getScbBodyFast().setFreezeThreshold(threshold); |
394 | } |
395 | |
396 | |
397 | PxReal NpRigidDynamic::getStabilizationThreshold() const |
398 | { |
399 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
400 | |
401 | return getScbBodyFast().getFreezeThreshold(); |
402 | } |
403 | |
404 | |
405 | void NpRigidDynamic::setWakeCounter(PxReal wakeCounterValue) |
406 | { |
407 | Scb::Body& b = getScbBodyFast(); |
408 | |
409 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
410 | PX_CHECK_AND_RETURN(PxIsFinite(wakeCounterValue), "PxRigidDynamic::setWakeCounter: invalid float." ); |
411 | PX_CHECK_AND_RETURN(wakeCounterValue>=0.0f, "PxRigidDynamic::setWakeCounter: wakeCounterValue must be non-negative!" ); |
412 | PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setWakeCounter: Body must be non-kinematic!" ); |
413 | PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setWakeCounter: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
414 | |
415 | b.setWakeCounter(wakeCounterValue); |
416 | } |
417 | |
418 | |
419 | PxReal NpRigidDynamic::getWakeCounter() const |
420 | { |
421 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
422 | |
423 | return getScbBodyFast().getWakeCounter(); |
424 | } |
425 | |
426 | |
427 | void NpRigidDynamic::wakeUp() |
428 | { |
429 | Scb::Body& b = getScbBodyFast(); |
430 | |
431 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
432 | PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::wakeUp: Body must be in a scene." ); |
433 | PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::wakeUp: Body must be non-kinematic!" ); |
434 | PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::wakeUp: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
435 | |
436 | b.wakeUp(); |
437 | } |
438 | |
439 | |
440 | void NpRigidDynamic::putToSleep() |
441 | { |
442 | Scb::Body& b = getScbBodyFast(); |
443 | |
444 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
445 | PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::putToSleep: Body must be in a scene." ); |
446 | PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::putToSleep: Body must be non-kinematic!" ); |
447 | PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::putToSleep: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!" ); |
448 | |
449 | b.putToSleep(); |
450 | } |
451 | |
452 | |
453 | void NpRigidDynamic::setSolverIterationCounts(PxU32 positionIters, PxU32 velocityIters) |
454 | { |
455 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
456 | PX_CHECK_AND_RETURN(positionIters > 0, "PxRigidDynamic::setSolverIterationCount: positionIters must be more than zero!" ); |
457 | PX_CHECK_AND_RETURN(positionIters <= 255, "PxRigidDynamic::setSolverIterationCount: positionIters must be no greater than 255!" ); |
458 | PX_CHECK_AND_RETURN(velocityIters <= 255, "PxRigidDynamic::setSolverIterationCount: velocityIters must be no greater than 255!" ); |
459 | |
460 | getScbBodyFast().setSolverIterationCounts((velocityIters & 0xff) << 8 | (positionIters & 0xff)); |
461 | } |
462 | |
463 | |
464 | void NpRigidDynamic::getSolverIterationCounts(PxU32 & positionIters, PxU32 & velocityIters) const |
465 | { |
466 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
467 | |
468 | PxU16 x = getScbBodyFast().getSolverIterationCounts(); |
469 | velocityIters = PxU32(x >> 8); |
470 | positionIters = PxU32(x & 0xff); |
471 | } |
472 | |
473 | |
474 | void NpRigidDynamic::setContactReportThreshold(PxReal threshold) |
475 | { |
476 | NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); |
477 | PX_CHECK_AND_RETURN(PxIsFinite(threshold), "PxRigidDynamic::setContactReportThreshold: invalid float." ); |
478 | PX_CHECK_AND_RETURN(threshold >= 0.0f, "PxRigidDynamic::setContactReportThreshold: Force threshold must be greater than zero!" ); |
479 | |
480 | getScbBodyFast().setContactReportThreshold(threshold<0 ? 0 : threshold); |
481 | } |
482 | |
483 | |
484 | PxReal NpRigidDynamic::getContactReportThreshold() const |
485 | { |
486 | NP_READ_CHECK(NpActor::getOwnerScene(*this)); |
487 | |
488 | return getScbBodyFast().getContactReportThreshold(); |
489 | } |
490 | |
491 | |
492 | PxU32 physx::NpRigidDynamicGetShapes(Scb::Body& body, void* const*& shapes, bool* isCompound) |
493 | { |
494 | NpRigidDynamic* a = static_cast<NpRigidDynamic*>(body.getScBody().getPxActor()); |
495 | NpShapeManager& sm = a->getShapeManager(); |
496 | shapes = reinterpret_cast<void *const *>(sm.getShapes()); |
497 | if(isCompound) |
498 | *isCompound = sm.isSqCompound(); |
499 | return sm.getNbShapes(); |
500 | } |
501 | |
502 | |
503 | void NpRigidDynamic::switchToNoSim() |
504 | { |
505 | getScbBodyFast().switchBodyToNoSim(); |
506 | } |
507 | |
508 | |
509 | void NpRigidDynamic::switchFromNoSim() |
510 | { |
511 | getScbBodyFast().switchFromNoSim(isDynamic: true); |
512 | } |
513 | |
514 | |
515 | void NpRigidDynamic::wakeUpInternalNoKinematicTest(Scb::Body& body, bool forceWakeUp, bool autowake) |
516 | { |
517 | NpScene* scene = NpActor::getOwnerScene(actor: *this); |
518 | PX_ASSERT(scene); |
519 | PxReal wakeCounterResetValue = scene->getWakeCounterResetValueInteral(); |
520 | |
521 | PxReal wakeCounter = body.getWakeCounter(); |
522 | |
523 | bool needsWakingUp = body.isSleeping() && (autowake || forceWakeUp); |
524 | if (autowake && (wakeCounter < wakeCounterResetValue)) |
525 | { |
526 | wakeCounter = wakeCounterResetValue; |
527 | needsWakingUp = true; |
528 | } |
529 | |
530 | if (needsWakingUp) |
531 | body.wakeUpInternal(wakeCounter); |
532 | } |
533 | |
534 | PxRigidDynamicLockFlags NpRigidDynamic::getRigidDynamicLockFlags() const |
535 | { |
536 | return mBody.getLockFlags(); |
537 | } |
538 | void NpRigidDynamic::setRigidDynamicLockFlags(PxRigidDynamicLockFlags flags) |
539 | { |
540 | mBody.setLockFlags(flags); |
541 | } |
542 | void NpRigidDynamic::setRigidDynamicLockFlag(PxRigidDynamicLockFlag::Enum flag, bool value) |
543 | { |
544 | PxRigidDynamicLockFlags flags = mBody.getLockFlags(); |
545 | if (value) |
546 | flags = flags | flag; |
547 | else |
548 | flags = flags & (~flag); |
549 | |
550 | mBody.setLockFlags(flags); |
551 | } |
552 | |
553 | |
554 | #if PX_ENABLE_DEBUG_VISUALIZATION |
555 | void NpRigidDynamic::visualize(Cm::RenderOutput& out, NpScene* npScene) |
556 | { |
557 | NpRigidDynamicT::visualize(out, scene: npScene); |
558 | |
559 | if (getScbBodyFast().getActorFlags() & PxActorFlag::eVISUALIZATION) |
560 | { |
561 | PX_ASSERT(npScene); |
562 | const PxReal scale = npScene->getVisualizationParameter(param: PxVisualizationParameter::eSCALE); |
563 | |
564 | const PxReal massAxes = scale * npScene->getVisualizationParameter(param: PxVisualizationParameter::eBODY_MASS_AXES); |
565 | if (massAxes != 0.0f) |
566 | { |
567 | PxReal sleepTime = getScbBodyFast().getWakeCounter() / npScene->getWakeCounterResetValueInteral(); |
568 | PxU32 color = PxU32(0xff * (sleepTime>1.0f ? 1.0f : sleepTime)); |
569 | color = getScbBodyFast().isSleeping() ? 0xff0000 : (color<<16 | color<<8 | color); |
570 | PxVec3 dims = invertDiagInertia(m: getScbBodyFast().getInverseInertia()); |
571 | dims = getDimsFromBodyInertia(inertiaMoments: dims, mass: 1.0f / getScbBodyFast().getInverseMass()); |
572 | |
573 | out << color << getScbBodyFast().getBody2World() << Cm::DebugBox(dims * 0.5f); |
574 | } |
575 | } |
576 | } |
577 | #endif |
578 | |