Panda3D
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 
23 TypeHandle PhysxCloth::_type_handle;
24 
25 /**
26  *
27  */
28 void PhysxCloth::
29 link(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  */
45 void PhysxCloth::
46 unlink() {
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  */
61 void PhysxCloth::
62 release() {
63 
64  nassertv(_error_type == ET_ok);
65 
66  unlink();
67  _ptr->getScene().releaseCloth(*_ptr);
68  _ptr = nullptr;
69 }
70 
71 /**
72  *
73  */
74 void PhysxCloth::
75 update() {
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 
87  PhysxManager::nxVec3_to_point3(bounds.max));
88  _node->set_bounds(&bb);
89  }
90 }
91 
92 /**
93  * Returns the scene which this cloth belongs to.
94  */
96 get_scene() const {
97 
98  nassertr(_error_type == ET_ok, nullptr);
99  return (PhysxScene *)_ptr->getScene().userData;
100 }
101 
102 /**
103  *
104  */
105 PhysxClothNode *PhysxCloth::
106 get_cloth_node() const {
107 
108  nassertr(_error_type == ET_ok, nullptr);
109  return _node;
110 }
111 
112 /**
113  *
114  */
115 PhysxClothNode *PhysxCloth::
116 create_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  */
130 void PhysxCloth::
131 set_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  */
142 const char *PhysxCloth::
143 get_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  */
153 void PhysxCloth::
154 set_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  */
164 unsigned int PhysxCloth::
165 get_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  */
174 void PhysxCloth::
175 set_thickness(float thickness) {
176 
177  nassertv(_error_type == ET_ok);
178  _ptr->setThickness(thickness);
179 }
180 
181 /**
182  * Gets the cloth thickness.
183  */
184 float PhysxCloth::
185 get_thickness() const {
186 
187  nassertr(_error_type == ET_ok, 0.0f);
188  return _ptr->getThickness();
189 }
190 
191 /**
192  * Gets the cloth density.
193  */
194 float PhysxCloth::
195 get_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  */
207 float PhysxCloth::
209 
210  nassertr(_error_type == ET_ok, 0.0f);
211  return _ptr->getRelativeGridSpacing();
212 }
213 
214 /**
215  * Gets the number of cloth particles.
216  */
217 unsigned 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  */
227 void PhysxCloth::
228 set_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  */
247 bool PhysxCloth::
248 get_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  */
258 void PhysxCloth::
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  */
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  */
292 bool PhysxCloth::
293 is_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  */
306 void PhysxCloth::
307 wake_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  */
320 void PhysxCloth::
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  */
334 void PhysxCloth::
335 set_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  */
346 float PhysxCloth::
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  */
356 void PhysxCloth::
357 attach_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  */
372 void PhysxCloth::
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  */
388 void PhysxCloth::
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  */
403 void PhysxCloth::
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  */
415 void PhysxCloth::
416 free_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  */
425 void PhysxCloth::
426 attach_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  */
441 PhysxEnums::PhysxVertexAttachmentStatus PhysxCloth::
442 get_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  */
456 get_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  */
472 LPoint3f PhysxCloth::
473 get_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  */
486 void PhysxCloth::
487 set_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  */
498 void PhysxCloth::
499 set_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  */
511 LVector3f PhysxCloth::
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  */
522 LVector3f PhysxCloth::
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  */
533 void PhysxCloth::
534 add_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  */
546 void PhysxCloth::
547 add_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  */
560 void PhysxCloth::
561 add_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 }
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
Definition: physxCloth.cxx:534
unsigned int get_num_particles()
Gets the number of cloth particles.
Definition: physxCloth.cxx:218
void wake_up(float wakeCounterValue=NX_SLEEP_INTERVAL)
Wakes up the cloth if it is sleeping.
Definition: physxCloth.cxx:307
PhysxScene * get_scene() const
Returns the scene which this cloth belongs to.
Definition: physxCloth.cxx:96
void attach_to_shape(PhysxShape *shape)
Attaches the cloth to a shape.
Definition: physxCloth.cxx:373
void detach_from_shape(PhysxShape *shape)
Detaches the cloth from a shape it has been attached to before.
Definition: physxCloth.cxx:404
static NxVec3 point3_to_nxVec3(const LPoint3f &p)
Converts from LPoint3f to NxVec3.
Definition: physxManager.I:63
Abstract base class for shapes.
Definition: physxShape.h:39
void set_name(const char *name)
Sets a name string for the object that can be retrieved with get_name().
Definition: physxCloth.cxx:131
void set_group(unsigned int group)
Sets which collision group this cloth is part of.
Definition: physxCloth.cxx:154
PhysxVertexAttachmentStatus get_vertex_attachment_status(unsigned int vertexId) const
Return the attachment status of the given vertex.
Definition: physxCloth.cxx:442
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
float get_thickness() const
Gets the cloth thickness.
Definition: physxCloth.cxx:185
void attach_to_colliding_shapes()
Attaches the cloth to all shapes, currently colliding.
Definition: physxCloth.cxx:389
A scene is a collection of bodies, constraints, and effectors which can interact.
Definition: physxScene.h:69
float get_relative_grid_spacing() const
Gets the relative grid spacing for the broad phase.
Definition: physxCloth.cxx:208
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
float get_density() const
Gets the cloth density.
Definition: physxCloth.cxx:195
void set_groups_mask(const PhysxGroupsMask &mask)
Sets 128-bit mask used for collision filtering.
Definition: physxCloth.cxx:259
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.
Definition: physxCloth.cxx:547
void put_to_sleep()
Forces the cloth to sleep.
Definition: physxCloth.cxx:321
PhysxShape * get_vertex_attachment_shape(unsigned int vertexId) const
Returns the pointer to an attached shape pointer of the given vertex.
Definition: physxCloth.cxx:456
void free_vertex(unsigned int vertexId)
Frees a previously attached cloth point.
Definition: physxCloth.cxx:416
void set_wind_acceleration(LVector3f const &acceleration)
Sets an acceleration acting normal to the cloth surface at each vertex.
Definition: physxCloth.cxx:499
LVector3f get_external_acceleration() const
Retrieves the external acceleration which affects all non attached particles of the cloth.
Definition: physxCloth.cxx:512
void attach_vertex_to_shape(unsigned int vertexId, PhysxShape *shape, LPoint3f const &localPos)
Attaches a cloth vertex to a local position within a shape.
Definition: physxCloth.cxx:426
static NxVec3 vec3_to_nxVec3(const LVector3f &v)
Converts from LVector3f to NxVec3.
Definition: physxManager.I:27
bool is_sleeping() const
Returns true if this cloth is sleeping.
Definition: physxCloth.cxx:293
void set_sleep_linear_velocity(float threshold)
Sets the linear velocity below which an cloth may go to sleep.
Definition: physxCloth.cxx:335
static LVector3f nxVec3_to_vec3(const NxVec3 &v)
Converts from NxVec3 to LVector3f.
Definition: physxManager.I:36
void set_external_acceleration(LVector3f const &acceleration)
Sets an external acceleration which affects all non attached particles of the cloth.
Definition: physxCloth.cxx:487
void attach_vertex_to_global_pos(unsigned int vertexId, LPoint3f const &pos)
Attaches a cloth vertex to a position in world space.
Definition: physxCloth.cxx:357
LVector3f get_wind_acceleration() const
Retrieves the acceleration acting normal to the cloth surface at each vertex.
Definition: physxCloth.cxx:523
LPoint3f get_vertex_attachment_pos(unsigned int vertexId) const
Returns the attachment position of the given vertex.
Definition: physxCloth.cxx:473
PhysxGroupsMask get_groups_mask() const
Gets the 128-bit groups mask used for collision filtering.
Definition: physxCloth.cxx:271
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_thickness(float thickness)
Sets the cloth thickness (must be positive).
Definition: physxCloth.cxx:175
static LPoint3f nxVec3_to_point3(const NxVec3 &p)
Converts from NxVec3 to LPoint3f.
Definition: physxManager.I:72
unsigned int get_group() const
Retrieves the collision group this cloth is part of.
Definition: physxCloth.cxx:165
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
const char * get_name() const
Retrieves the name string.
Definition: physxCloth.cxx:143
void set_flag(PhysxClothFlag flag, bool value)
Sets the value of a single flag.
Definition: physxCloth.cxx:228
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
Definition: physxCloth.cxx:561
Renderable geometry which represents a cloth mesh.
bool get_flag(PhysxClothFlag flag) const
Retrieves the value of a single flag.
Definition: physxCloth.cxx:248
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
128-bit bitmask class.
float get_sleep_linear_velocity() const
Returns the linear velocity below which an soft body may go to sleep.
Definition: physxCloth.cxx:347