Panda3D
Loading...
Searching...
No Matches
physxCloth.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file physxCloth.cxx
10 * @author enn0x
11 * @date 2010-03-30
12 */
13
14#include "physxCloth.h"
15#include "physxClothDesc.h"
16#include "physxScene.h"
17#include "physxGroupsMask.h"
18#include "physxShape.h"
19#include "physxManager.h"
20
21#include "boundingBox.h"
22
23TypeHandle PhysxCloth::_type_handle;
24
25/**
26 *
27 */
28void PhysxCloth::
29link(NxCloth *clothPtr) {
30
31 // Link self
32 _ptr = clothPtr;
33 _error_type = ET_ok;
34 _ptr->userData = this;
35
36 set_name(clothPtr->getName());
37
38 PhysxScene *scene = (PhysxScene *)_ptr->getScene().userData;
39 scene->_cloths.add(this);
40}
41
42/**
43 *
44 */
45void PhysxCloth::
46unlink() {
47
48 // Unlink self
49 _ptr->userData = nullptr;
50 _error_type = ET_released;
51
52 PhysxScene *scene = (PhysxScene *)_ptr->getScene().userData;
53 scene->_cloths.remove(this);
54
55 _node = nullptr;
56}
57
58/**
59 *
60 */
61void PhysxCloth::
62release() {
63
64 nassertv(_error_type == ET_ok);
65
66 unlink();
67 _ptr->getScene().releaseCloth(*_ptr);
68 _ptr = nullptr;
69}
70
71/**
72 *
73 */
74void PhysxCloth::
75update() {
76
77 if (_node) {
78
79 // Update node mesh data
80 _node->update();
81
82 // Update node bounding volume
83 NxBounds3 bounds;
84 _ptr->getWorldBounds(bounds);
85
88 _node->set_bounds(&bb);
89 }
90}
91
92/**
93 * Returns the scene which this cloth belongs to.
94 */
96get_scene() const {
97
98 nassertr(_error_type == ET_ok, nullptr);
99 return (PhysxScene *)_ptr->getScene().userData;
100}
101
102/**
103 *
104 */
105PhysxClothNode *PhysxCloth::
106get_cloth_node() const {
107
108 nassertr(_error_type == ET_ok, nullptr);
109 return _node;
110}
111
112/**
113 *
114 */
115PhysxClothNode *PhysxCloth::
116create_cloth_node(const char *name) {
117
118 nassertr(_error_type == ET_ok, nullptr);
119
120 _node = new PhysxClothNode(name);
121 _node->allocate(this);
122
123 return _node;
124}
125
126/**
127 * Sets a name string for the object that can be retrieved with get_name().
128 * This is for debugging and is not used by the engine.
129 */
131set_name(const char *name) {
132
133 nassertv(_error_type == ET_ok);
134
135 _name = name ? name : "";
136 _ptr->setName(_name.c_str());
137}
138
139/**
140 * Retrieves the name string.
141 */
142const char *PhysxCloth::
143get_name() const {
144
145 nassertr(_error_type == ET_ok, "");
146 return _ptr->getName();
147}
148
149/**
150 * Sets which collision group this cloth is part of. Collision group must be
151 * between 0 and 31.
152 */
154set_group(unsigned int group) {
155
156 nassertv(_error_type == ET_ok);
157 nassertv(group >= 0 && group < 32);
158 _ptr->setGroup(group);
159}
160
161/**
162 * Retrieves the collision group this cloth is part of.
163 */
164unsigned int PhysxCloth::
165get_group() const {
166
167 nassertr(_error_type == ET_ok, 0);
168 return _ptr->getGroup();
169}
170
171/**
172 * Sets the cloth thickness (must be positive).
173 */
175set_thickness(float thickness) {
176
177 nassertv(_error_type == ET_ok);
178 _ptr->setThickness(thickness);
179}
180
181/**
182 * Gets the cloth thickness.
183 */
185get_thickness() const {
186
187 nassertr(_error_type == ET_ok, 0.0f);
188 return _ptr->getThickness();
189}
190
191/**
192 * Gets the cloth density.
193 */
195get_density() const {
196
197 nassertr(_error_type == ET_ok, 0.0f);
198 return _ptr->getDensity();
199}
200
201/**
202 * Gets the relative grid spacing for the broad phase. The cloth is
203 * represented by a set of world aligned cubical cells in broad phase. The
204 * size of these cells is determined by multiplying the length of the diagonal
205 * of the AABB of the initial soft body size with this constant.
206 */
209
210 nassertr(_error_type == ET_ok, 0.0f);
211 return _ptr->getRelativeGridSpacing();
212}
213
214/**
215 * Gets the number of cloth particles.
216 */
217unsigned int PhysxCloth::
219
220 nassertr(_error_type == ET_ok, 0);
221 return _ptr->getNumberOfParticles();
222}
223
224/**
225 * Sets the value of a single flag.
226 */
228set_flag(PhysxClothFlag flag, bool value) {
229
230 nassertv(_error_type == ET_ok);
231
232 NxU32 flags = _ptr->getFlags();
233
234 if (value == true) {
235 flags |= flag;
236 }
237 else {
238 flags &= ~(flag);
239 }
240
241 _ptr->setFlags(flags);
242}
243
244/**
245 * Retrieves the value of a single flag.
246 */
248get_flag(PhysxClothFlag flag) const {
249
250 nassertr(_error_type == ET_ok, false);
251
252 return (_ptr->getFlags() & flag) ? true : false;
253}
254
255/**
256 * Sets 128-bit mask used for collision filtering.
257 */
259set_groups_mask(const PhysxGroupsMask &mask) {
260
261 nassertv(_error_type == ET_ok);
262
263 NxGroupsMask _mask = mask.get_mask();
264 _ptr->setGroupsMask(_mask);
265}
266
267/**
268 * Gets the 128-bit groups mask used for collision filtering.
269 */
271get_groups_mask() const {
272
273 PhysxGroupsMask mask;
274
275 nassertr(_error_type == ET_ok, mask);
276
277 NxGroupsMask _mask = _ptr->getGroupsMask();
278 mask.set_mask(_mask);
279
280 return mask;
281}
282
283/**
284 * Returns true if this cloth is sleeping.
285 *
286 * When a cloth does not move for a period of time, it is no longer simulated
287 * in order to save time. This state is called sleeping. However, because
288 * the object automatically wakes up when it is either touched by an awake
289 * object, or one of its properties is changed by the user, the entire sleep
290 * mechanism should be transparent to the user.
291 */
293is_sleeping() const {
294
295 nassertr(_error_type == ET_ok, false);
296 return _ptr->isSleeping();
297}
298
299/**
300 * Wakes up the cloth if it is sleeping.
301 *
302 * The wakeCounterValue determines how long until the body is put to sleep, a
303 * value of zero means that the body is sleeping. wake_up(0) is equivalent to
304 * PhysxCloth::put_to_sleep().
305 */
307wake_up(float wakeCounterValue) {
308
309 nassertv(_error_type == ET_ok);
310 _ptr->wakeUp(wakeCounterValue);
311}
312
313/**
314 * Forces the cloth to sleep.
315 *
316 * The cloth will stay asleep until the next call to simulate, and will not
317 * wake up until then even when otherwise it would (for example a force is
318 * applied to it). It can however wake up during the next do_physics call.
319 */
321put_to_sleep() {
322
323 nassertv(_error_type == ET_ok);
324 _ptr->putToSleep();
325}
326
327/**
328 * Sets the linear velocity below which an cloth may go to sleep. Cloths
329 * whose linear velocity is above this threshold will not be put to sleep.
330 *
331 * Setting the sleep angular/linear velocity only makes sense when the
332 * BF_energy_sleep_test is not set.
333 */
335set_sleep_linear_velocity(float threshold) {
336
337 nassertv(_error_type == ET_ok);
338 _ptr->setSleepLinearVelocity(threshold);
339}
340
341/**
342 * Returns the linear velocity below which an soft body may go to sleep.
343 * cloths whose linear velocity is above this threshold will not be put to
344 * sleep.
345 */
348
349 nassertr(_error_type == ET_ok, 0.0f);
350 return _ptr->getSleepLinearVelocity();
351}
352
353/**
354 * Attaches a cloth vertex to a position in world space.
355 */
357attach_vertex_to_global_pos(unsigned int vertexId, LPoint3f const &pos) {
358
359 nassertv(_error_type == ET_ok);
360 nassertv(!pos.is_nan());
361
362 _ptr->attachVertexToGlobalPosition(vertexId, PhysxManager::point3_to_nxVec3(pos));
363}
364
365/**
366 * Attaches the cloth to a shape. All cloth points currently inside the shape
367 * are attached.
368 *
369 * This method only works with primitive and convex shapes. Since the inside
370 * of a general triangle mesh is not clearly defined.
371 */
374
375 nassertv(_error_type == ET_ok);
376 nassertv(shape);
377
378 NxU32 attachmentFlags = 0; // --TODO--
379 _ptr->attachToShape(shape->ptr(), attachmentFlags);
380}
381
382/**
383 * Attaches the cloth to all shapes, currently colliding.
384 *
385 * This method only works with primitive and convex shapes. Since the inside
386 * of a general triangle mesh is not clearly defined.
387 */
390
391 nassertv(_error_type == ET_ok);
392
393 NxU32 attachmentFlags = 0; // --TODO--
394 _ptr->attachToCollidingShapes(attachmentFlags);
395}
396
397/**
398 * Detaches the cloth from a shape it has been attached to before.
399 *
400 * If the cloth has not been attached to the shape before, the call has no
401 * effect.
402 */
405
406 nassertv(_error_type == ET_ok);
407 nassertv(shape);
408
409 _ptr->detachFromShape(shape->ptr());
410}
411
412/**
413 * Frees a previously attached cloth point.
414 */
416free_vertex(unsigned int vertexId) {
417
418 nassertv(_error_type == ET_ok);
419 _ptr->freeVertex(vertexId);
420}
421
422/**
423 * Attaches a cloth vertex to a local position within a shape.
424 */
426attach_vertex_to_shape(unsigned int vertexId, PhysxShape *shape, LPoint3f const &localPos) {
427
428 nassertv(_error_type == ET_ok);
429 nassertv(!localPos.is_nan());
430 nassertv(shape);
431
432 NxU32 attachmentFlags = 0; // --TODO--
433 _ptr->attachVertexToShape(vertexId, shape->ptr(),
435 attachmentFlags);
436}
437
438/**
439 * Return the attachment status of the given vertex.
440 */
441PhysxEnums::PhysxVertexAttachmentStatus PhysxCloth::
442get_vertex_attachment_status(unsigned int vertexId) const {
443
444 nassertr(_error_type == ET_ok, VAS_none);
445 // --TODO-- nassertr(vertexId < _ptr->getNumberOfParticles(), VAS_none);
446
447 return (PhysxVertexAttachmentStatus) _ptr->getVertexAttachmentStatus(vertexId);
448}
449
450/**
451 * Returns the pointer to an attached shape pointer of the given vertex. If
452 * the vertex is not attached or attached to a global position, NULL is
453 * returned.
454 */
456get_vertex_attachment_shape(unsigned int vertexId) const {
457
458 nassertr(_error_type == ET_ok, nullptr);
459 // --TODO-- nassertr(vertexId < _ptr->getNumberOfParticles(), NULL);
460
461 NxShape *shapePtr = _ptr->getVertexAttachmentShape(vertexId);
462 PhysxShape *shape = shapePtr ? (PhysxShape *)(shapePtr->userData) : nullptr;
463
464 return shape;
465}
466
467/**
468 * Returns the attachment position of the given vertex. If the vertex is
469 * attached to shape, the position local to the shape's pose is returned. If
470 * the vertex is not attached, the return value is undefined.
471 */
473get_vertex_attachment_pos(unsigned int vertexId) const {
474
475 nassertr(_error_type == ET_ok, LPoint3f::zero());
476 // --TODO-- nassertr(vertexId < _ptr->getNumberOfParticles(),
477 // LPoint3f::zero());
478
479 return PhysxManager::nxVec3_to_point3(_ptr->getVertexAttachmentPosition(vertexId));
480}
481
482/**
483 * Sets an external acceleration which affects all non attached particles of
484 * the cloth.
485 */
487set_external_acceleration(LVector3f const &acceleration) {
488
489 nassertv(_error_type == ET_ok);
490 nassertv_always(!acceleration.is_nan());
491
492 _ptr->setExternalAcceleration(PhysxManager::vec3_to_nxVec3(acceleration));
493}
494
495/**
496 * Sets an acceleration acting normal to the cloth surface at each vertex.
497 */
499set_wind_acceleration(LVector3f const &acceleration) {
500
501 nassertv(_error_type == ET_ok);
502 nassertv_always(!acceleration.is_nan());
503
504 _ptr->setWindAcceleration(PhysxManager::vec3_to_nxVec3(acceleration));
505}
506
507/**
508 * Retrieves the external acceleration which affects all non attached
509 * particles of the cloth.
510 */
513
514 nassertr(_error_type == ET_ok, LVector3f::zero());
515 return PhysxManager::nxVec3_to_vec3(_ptr->getExternalAcceleration());
516}
517
518/**
519 * Retrieves the acceleration acting normal to the cloth surface at each
520 * vertex
521 */
523get_wind_acceleration() const {
524
525 nassertr(_error_type == ET_ok, LVector3f::zero());
526 return PhysxManager::nxVec3_to_vec3(_ptr->getWindAcceleration());
527}
528
529/**
530 * Applies a force (or impulse) defined in the global coordinate frame, to a
531 * particular vertex of the cloth.
532 */
534add_force_at_vertex(LVector3f const &force, int vertexId, PhysxForceMode mode) {
535
536 nassertv(_error_type == ET_ok);
537 _ptr->addForceAtVertex(PhysxManager::vec3_to_nxVec3(force),
538 vertexId,
539 (NxForceMode) mode);
540}
541
542/**
543 * Applies a radial force (or impulse) at a particular position. All vertices
544 * within radius will be affected with a quadratic drop-off.
545 */
547add_force_at_pos(LPoint3f const &pos, float magnitude, float radius, PhysxForceMode mode) {
548
549 nassertv(_error_type == ET_ok);
550 _ptr->addForceAtPos(PhysxManager::point3_to_nxVec3(pos),
551 magnitude,
552 radius,
553 (NxForceMode) mode);
554}
555
556/**
557 * Applies a directed force (or impulse) at a particular position. All
558 * vertices within radius will be affected with a quadratic drop-off.
559 */
561add_directed_force_at_pos(LPoint3f const &pos, LVector3f const &force, float radius, PhysxForceMode mode) {
562
563 nassertv(_error_type == ET_ok);
564 _ptr->addDirectedForceAtPos(PhysxManager::point3_to_nxVec3(pos),
566 radius,
567 (NxForceMode) mode);
568}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition boundingBox.h:29
Renderable geometry which represents a cloth mesh.
void set_wind_acceleration(LVector3f const &acceleration)
Sets an acceleration acting normal to the cloth surface at each vertex.
void put_to_sleep()
Forces the cloth to sleep.
float get_thickness() const
Gets the cloth thickness.
float get_relative_grid_spacing() const
Gets the relative grid spacing for the broad phase.
LVector3f get_external_acceleration() const
Retrieves the external acceleration which affects all non attached particles of the cloth.
void attach_vertex_to_global_pos(unsigned int vertexId, LPoint3f const &pos)
Attaches a cloth vertex to a position in world space.
LVector3f get_wind_acceleration() const
Retrieves the acceleration acting normal to the cloth surface at each vertex.
void detach_from_shape(PhysxShape *shape)
Detaches the cloth from a shape it has been attached to before.
void add_force_at_vertex(LVector3f const &force, int vertexId, PhysxForceMode mode=FM_force)
Applies a force (or impulse) defined in the global coordinate frame, to a particular vertex of the cl...
void set_group(unsigned int group)
Sets which collision group this cloth is part of.
void attach_vertex_to_shape(unsigned int vertexId, PhysxShape *shape, LPoint3f const &localPos)
Attaches a cloth vertex to a local position within a shape.
void add_force_at_pos(LPoint3f const &pos, float magnitude, float radius, PhysxForceMode mode=FM_force)
Applies a radial force (or impulse) at a particular position.
void add_directed_force_at_pos(LPoint3f const &pos, LVector3f const &force, float radius, PhysxForceMode mode=FM_force)
Applies a directed force (or impulse) at a particular position.
void set_external_acceleration(LVector3f const &acceleration)
Sets an external acceleration which affects all non attached particles of the cloth.
void set_sleep_linear_velocity(float threshold)
Sets the linear velocity below which an cloth may go to sleep.
const char * get_name() const
Retrieves the name string.
void set_groups_mask(const PhysxGroupsMask &mask)
Sets 128-bit mask used for collision filtering.
void set_flag(PhysxClothFlag flag, bool value)
Sets the value of a single flag.
float get_sleep_linear_velocity() const
Returns the linear velocity below which an soft body may go to sleep.
PhysxVertexAttachmentStatus get_vertex_attachment_status(unsigned int vertexId) const
Return the attachment status of the given vertex.
unsigned int get_num_particles()
Gets the number of cloth particles.
void wake_up(float wakeCounterValue=NX_SLEEP_INTERVAL)
Wakes up the cloth if it is sleeping.
void attach_to_shape(PhysxShape *shape)
Attaches the cloth to a shape.
LPoint3f get_vertex_attachment_pos(unsigned int vertexId) const
Returns the attachment position of the given vertex.
float get_density() const
Gets the cloth density.
void attach_to_colliding_shapes()
Attaches the cloth to all shapes, currently colliding.
PhysxGroupsMask get_groups_mask() const
Gets the 128-bit groups mask used for collision filtering.
void set_thickness(float thickness)
Sets the cloth thickness (must be positive).
bool get_flag(PhysxClothFlag flag) const
Retrieves the value of a single flag.
PhysxShape * get_vertex_attachment_shape(unsigned int vertexId) const
Returns the pointer to an attached shape pointer of the given vertex.
unsigned int get_group() const
Retrieves the collision group this cloth is part of.
void set_name(const char *name)
Sets a name string for the object that can be retrieved with get_name().
bool is_sleeping() const
Returns true if this cloth is sleeping.
PhysxScene * get_scene() const
Returns the scene which this cloth belongs to.
void free_vertex(unsigned int vertexId)
Frees a previously attached cloth point.
128-bit bitmask class.
static NxVec3 vec3_to_nxVec3(const LVector3f &v)
Converts from LVector3f to NxVec3.
static NxVec3 point3_to_nxVec3(const LPoint3f &p)
Converts from LPoint3f to NxVec3.
static LPoint3f nxVec3_to_point3(const NxVec3 &p)
Converts from NxVec3 to LPoint3f.
static LVector3f nxVec3_to_vec3(const NxVec3 &v)
Converts from NxVec3 to LVector3f.
A scene is a collection of bodies, constraints, and effectors which can interact.
Definition physxScene.h:69
Abstract base class for shapes.
Definition physxShape.h:39
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.