LiquidFun
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
b2ParticleSystem.h
1 /*
2 * Copyright (c) 2013 Google, Inc.
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 * 1. The origin of this software must not be misrepresented; you must not
11 * claim that you wrote the original software. If you use this software
12 * in a product, an acknowledgment in the product documentation would be
13 * appreciated but is not required.
14 * 2. Altered source versions must be plainly marked as such, and must not be
15 * misrepresented as being the original software.
16 * 3. This notice may not be removed or altered from any source distribution.
17 */
18 #ifndef B2_PARTICLE_SYSTEM_H
19 #define B2_PARTICLE_SYSTEM_H
20 
21 #include <Box2D/Common/b2SlabAllocator.h>
22 #include <Box2D/Common/b2GrowableBuffer.h>
24 #include <Box2D/Dynamics/b2TimeStep.h>
25 
26 #if LIQUIDFUN_UNIT_TESTS
27 #include <gtest/gtest.h>
28 #endif // LIQUIDFUN_UNIT_TESTS
29 
30 #if LIQUIDFUN_EXTERNAL_LANGUAGE_API
31 #include <cstring>
32 #endif // LIQUIDFUN_EXTERNAL_LANGUAGE_API
33 
34 class b2World;
35 class b2Body;
36 class b2Shape;
37 class b2ParticleGroup;
38 class b2BlockAllocator;
39 class b2StackAllocator;
40 class b2QueryCallback;
41 class b2RayCastCallback;
42 class b2Fixture;
43 class b2ContactFilter;
44 class b2ContactListener;
45 class b2ParticlePairSet;
46 class FixtureParticleSet;
47 struct b2ParticleGroupDef;
48 struct b2Vec2;
49 struct b2AABB;
50 struct FindContactInput;
51 struct FindContactCheck;
52 
54 {
55 private:
56  // 16-bit particle indices consume less memory and thus improve
57  // performance. We iterate through m_contactBuffer many times during
58  // b2ParticleSystem::Solve, so reducing the amount of data we churn
59  // through speeds things up. Also, FindContactsFromChecks_Simd takes
60  // advantage of the reduced size for specific optimizations.
61  #ifdef B2_USE_16_BIT_PARTICLE_INDICES
62  typedef int16 b2ParticleIndex;
63  #else
64  typedef int32 b2ParticleIndex;
65  #endif
66 
68  b2ParticleIndex indexA, indexB;
69 
73  float32 weight;
74 
76  b2Vec2 normal;
77 
80  uint32 flags;
81 
82 public:
83  void SetIndices(int32 a, int32 b);
84  void SetWeight(float32 w) { weight = w; }
85  void SetNormal(const b2Vec2& n) { normal = n; }
86  void SetFlags(uint32 f) { flags = f; }
87 
88  int32 GetIndexA() const { return indexA; }
89  int32 GetIndexB() const { return indexB; }
90  float32 GetWeight() const { return weight; }
91  const b2Vec2& GetNormal() const { return normal; }
92  uint32 GetFlags() const { return flags; }
93 
94  bool operator==(const b2ParticleContact& rhs) const;
95  bool operator!=(const b2ParticleContact& rhs) const { return !operator==(rhs); }
96  bool ApproximatelyEqual(const b2ParticleContact& rhs) const;
97 };
98 
100 {
102  int32 index;
103 
106 
109 
111  float32 weight;
112 
115 
117  float32 mass;
118 };
119 
122 {
124  int32 indexA, indexB;
125 
127  uint32 flags;
128 
130  float32 strength;
131 
133  float32 distance;
134 };
135 
138 {
140  int32 indexA, indexB, indexC;
141 
143  uint32 flags;
144 
146  float32 strength;
147 
149  b2Vec2 pa, pb, pc;
150  float32 ka, kb, kc, s;
151 };
152 
154 {
156  {
157  strictContactCheck = false;
158  density = 1.0f;
159  gravityScale = 1.0f;
160  radius = 1.0f;
161  maxCount = 0;
162 
163  // Initialize physical coefficients to the maximum values that
164  // maintain numerical stability.
165  pressureStrength = 0.05f;
166  dampingStrength = 1.0f;
167  elasticStrength = 0.25f;
168  springStrength = 0.25f;
169  viscousStrength = 0.25f;
172  repulsiveStrength = 1.0f;
173  powderStrength = 0.5f;
174  ejectionStrength = 0.5f;
175  staticPressureStrength = 0.2f;
178  colorMixingStrength = 0.5f;
179  destroyByAge = true;
180  lifetimeGranularity = 1.0f / 60.0f;
181  }
182 
186 
189  float32 density;
190 
193  float32 gravityScale;
194 
196  float32 radius;
197 
202  int32 maxCount;
203 
207 
211 
215 
218  float32 springStrength;
219 
223 
227 
232 
238 
241  float32 powderStrength;
242 
246 
252 
256 
260 
265 
270 
278 };
279 
280 
282 {
283 public:
291  int32 CreateParticle(const b2ParticleDef& def);
292 
295  const b2ParticleHandle* GetParticleHandleFromIndex(const int32 index);
296 
300  void DestroyParticle(int32 index)
301  {
302  DestroyParticle(index, false);
303  }
304 
310  void DestroyParticle(int32 index, bool callDestructionListener);
311 
319  void DestroyOldestParticle(const int32 index,
320  const bool callDestructionListener);
321 
331  int32 DestroyParticlesInShape(const b2Shape& shape, const b2Transform& xf)
332  {
333  return DestroyParticlesInShape(shape, xf, false);
334  }
335 
347  int32 DestroyParticlesInShape(const b2Shape& shape, const b2Transform& xf,
348  bool callDestructionListener);
349 
354 
359  void JoinParticleGroups(b2ParticleGroup* groupA, b2ParticleGroup* groupB);
360 
364  void SplitParticleGroup(b2ParticleGroup* group);
365 
371  const b2ParticleGroup* GetParticleGroupList() const;
372 
374  int32 GetParticleGroupCount() const;
375 
377  int32 GetParticleCount() const;
378 
380  int32 GetMaxParticleCount() const;
381 
389  void SetMaxParticleCount(int32 count);
390 
392  uint32 GetAllParticleFlags() const;
393 
395  uint32 GetAllGroupFlags() const;
396 
401  void SetPaused(bool paused);
402 
406  bool GetPaused() const;
407 
412  void SetDensity(float32 density);
413 
415  float32 GetDensity() const;
416 
419  void SetGravityScale(float32 gravityScale);
420 
422  float32 GetGravityScale() const;
423 
427  void SetDamping(float32 damping);
428 
430  float32 GetDamping() const;
431 
440  void SetStaticPressureIterations(int32 iterations);
441 
443  int32 GetStaticPressureIterations() const;
444 
449  void SetRadius(float32 radius);
450 
452  float32 GetRadius() const;
453 
458  const b2Vec2* GetPositionBuffer() const;
459 
464  const b2Vec2* GetVelocityBuffer() const;
465 
470  const b2ParticleColor* GetColorBuffer() const;
471 
476  const b2ParticleGroup* const* GetGroupBuffer() const;
477 
481  float32* GetWeightBuffer();
482  const float32* GetWeightBuffer() const;
483 
487  void** GetUserDataBuffer();
488  void* const* GetUserDataBuffer() const;
489 
493  const uint32* GetFlagsBuffer() const;
494 
496  void SetParticleFlags(int32 index, uint32 flags);
498  uint32 GetParticleFlags(const int32 index);
499 
512  void SetFlagsBuffer(uint32* buffer, int32 capacity);
513  void SetPositionBuffer(b2Vec2* buffer, int32 capacity);
514  void SetVelocityBuffer(b2Vec2* buffer, int32 capacity);
515  void SetColorBuffer(b2ParticleColor* buffer, int32 capacity);
516  void SetUserDataBuffer(void** buffer, int32 capacity);
517 
521  const b2ParticleContact* GetContacts() const;
522  int32 GetContactCount() const;
523 
527  const b2ParticleBodyContact* GetBodyContacts() const;
528  int32 GetBodyContactCount() const;
529 
543  const b2ParticlePair* GetPairs() const;
544  int32 GetPairCount() const;
545 
560  const b2ParticleTriad* GetTriads() const;
561  int32 GetTriadCount() const;
562 
567  void SetStuckThreshold(int32 iterations);
568 
571  const int32* GetStuckCandidates() const;
572 
574  int32 GetStuckCandidateCount() const;
575 
577  float32 ComputeCollisionEnergy() const;
578 
586  void SetStrictContactCheck(bool enabled);
588  bool GetStrictContactCheck() const;
589 
593  void SetParticleLifetime(const int32 index, const float32 lifetime);
598  float32 GetParticleLifetime(const int32 index);
599 
608  void SetDestructionByAge(const bool enable);
611  bool GetDestructionByAge() const;
612 
615  const int32* GetExpirationTimeBuffer();
619  float32 ExpirationTimeToLifetime(const int32 expirationTime) const;
628  const int32* GetIndexByExpirationTimeBuffer();
629 
635  void ParticleApplyLinearImpulse(int32 index, const b2Vec2& impulse);
636 
647  void ApplyLinearImpulse(int32 firstIndex, int32 lastIndex,
648  const b2Vec2& impulse);
649 
653  void ParticleApplyForce(int32 index, const b2Vec2& force);
654 
662  void ApplyForce(int32 firstIndex, int32 lastIndex, const b2Vec2& force);
663 
666  const b2ParticleSystem* GetNext() const;
667 
673  void QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const;
674 
681  void QueryShapeAABB(b2QueryCallback* callback, const b2Shape& shape,
682  const b2Transform& xf) const;
683 
691  void RayCast(b2RayCastCallback* callback, const b2Vec2& point1,
692  const b2Vec2& point2) const;
693 
697  void ComputeAABB(b2AABB* const aabb) const;
698 
699 #if LIQUIDFUN_EXTERNAL_LANGUAGE_API
700 public:
701  enum b2ExceptionType
702  {
703  b2_bufferTooSmall,
704  b2_particleIndexOutOfBounds,
705  b2_numErrors,
706  b2_noExceptions,
707  };
708 
710  void SetParticleVelocity(int32 index, float32 vx, float32 vy);
711 
713  float GetParticlePositionX(int32 index) const;
714 
716  float GetParticlePositionY(int32 index) const;
717 
719  int CopyPositionBuffer(int startIndex, int numParticles, void* outBuf,
720  int size) const;
721 
723  int CopyColorBuffer(int startIndex, int numParticles, void* outBuf,
724  int size) const;
725 
727  int CopyWeightBuffer(int startIndex, int numParticles, void* outBuf,
728  int size) const;
729 
730 private:
732  int CopyBuffer(int startIndex, int numParticles, void* inBufWithOffset,
733  void* outBuf, int outBufSize, int copySize) const;
734 
737  b2ExceptionType IsBufCopyValid(int startIndex, int numParticles,
738  int copySize, int bufSize) const;
739 #endif // LIQUIDFUN_EXTERNAL_LANGUAGE_API
740 
741 private:
742  friend class b2World;
743  friend class b2ParticleGroup;
744  friend class b2ParticleBodyContactRemovePredicate;
745  friend class b2FixtureParticleQueryCallback;
746 #ifdef LIQUIDFUN_UNIT_TESTS
747  FRIEND_TEST(FunctionTests, GetParticleMass);
748  FRIEND_TEST(FunctionTests, AreProxyBuffersTheSame);
749 #endif // LIQUIDFUN_UNIT_TESTS
750 
751  template <typename T>
752  struct UserOverridableBuffer
753  {
754  UserOverridableBuffer()
755  {
756  data = NULL;
757  userSuppliedCapacity = 0;
758  }
759  T* data;
760  int32 userSuppliedCapacity;
761  };
762 
764  struct Proxy
765  {
766  int32 index;
767  uint32 tag;
768  friend inline bool operator<(const Proxy &a, const Proxy &b)
769  {
770  return a.tag < b.tag;
771  }
772  friend inline bool operator<(uint32 a, const Proxy &b)
773  {
774  return a < b.tag;
775  }
776  friend inline bool operator<(const Proxy &a, uint32 b)
777  {
778  return a.tag < b;
779  }
780  };
781 
783  class ConnectionFilter
784  {
785  public:
786  virtual ~ConnectionFilter() {}
789  virtual bool IsNecessary(int32 index) const
790  {
791  B2_NOT_USED(index);
792  return true;
793  }
795  virtual bool ShouldCreatePair(int32 a, int32 b) const
796  {
797  B2_NOT_USED(a);
798  B2_NOT_USED(b);
799  return true;
800  }
802  virtual bool ShouldCreateTriad(int32 a, int32 b, int32 c) const
803  {
804  B2_NOT_USED(a);
805  B2_NOT_USED(b);
806  B2_NOT_USED(c);
807  return true;
808  }
809  };
810 
812  class InsideBoundsEnumerator
813  {
814  public:
816  InsideBoundsEnumerator(
817  uint32 lower, uint32 upper,
818  const Proxy* first, const Proxy* last);
819 
822  int32 GetNext();
823  private:
825  uint32 m_xLower, m_xUpper;
827  uint32 m_yLower, m_yUpper;
829  const Proxy* m_first;
830  const Proxy* m_last;
831  };
832 
834  struct ParticleListNode
835  {
837  ParticleListNode* list;
839  ParticleListNode* next;
842  int32 count;
844  int32 index;
845  };
846 
848  static const int32 k_pairFlags =
852  static const int32 k_triadFlags =
855  static const int32 k_noPressureFlags =
859  static const int32 k_extraDampingFlags =
861 
862  b2ParticleSystem(const b2ParticleSystemDef* def, b2World* world);
863  ~b2ParticleSystem();
864 
865  template <typename T> void FreeBuffer(T** b, int capacity);
866  template <typename T> void FreeUserOverridableBuffer(
867  UserOverridableBuffer<T>* b);
868  template <typename T> T* ReallocateBuffer(T* buffer, int32 oldCapacity,
869  int32 newCapacity);
870  template <typename T> T* ReallocateBuffer(
871  T* buffer, int32 userSuppliedCapacity, int32 oldCapacity,
872  int32 newCapacity, bool deferred);
873  template <typename T> T* ReallocateBuffer(
874  UserOverridableBuffer<T>* buffer, int32 oldCapacity, int32 newCapacity,
875  bool deferred);
876  template <typename T> T* RequestBuffer(T* buffer);
877 
880  void ReallocateHandleBuffers(int32 newCapacity);
881 
882  void ReallocateInternalAllocatedBuffers(int32 capacity);
883  int32 CreateParticleForGroup(
884  const b2ParticleGroupDef& groupDef,
885  const b2Transform& xf, const b2Vec2& position);
886  void CreateParticlesStrokeShapeForGroup(
887  const b2Shape* shape,
888  const b2ParticleGroupDef& groupDef, const b2Transform& xf);
889  void CreateParticlesFillShapeForGroup(
890  const b2Shape* shape,
891  const b2ParticleGroupDef& groupDef, const b2Transform& xf);
892  void CreateParticlesWithShapeForGroup(
893  const b2Shape* shape,
894  const b2ParticleGroupDef& groupDef, const b2Transform& xf);
895  void CreateParticlesWithShapesForGroup(
896  const b2Shape* const* shapes, int32 shapeCount,
897  const b2ParticleGroupDef& groupDef, const b2Transform& xf);
898  int32 CloneParticle(int32 index, b2ParticleGroup* group);
899  void DestroyParticleGroup(b2ParticleGroup* group);
900 
901  void UpdatePairsAndTriads(
902  int32 firstIndex, int32 lastIndex, const ConnectionFilter& filter);
903  void UpdatePairsAndTriadsWithReactiveParticles();
904  static bool ComparePairIndices(const b2ParticlePair& a, const b2ParticlePair& b);
905  static bool MatchPairIndices(const b2ParticlePair& a, const b2ParticlePair& b);
906  static bool CompareTriadIndices(const b2ParticleTriad& a, const b2ParticleTriad& b);
907  static bool MatchTriadIndices(const b2ParticleTriad& a, const b2ParticleTriad& b);
908 
909  static void InitializeParticleLists(
910  const b2ParticleGroup* group, ParticleListNode* nodeBuffer);
911  void MergeParticleListsInContact(
912  const b2ParticleGroup* group, ParticleListNode* nodeBuffer) const;
913  static void MergeParticleLists(
914  ParticleListNode* listA, ParticleListNode* listB);
915  static ParticleListNode* FindLongestParticleList(
916  const b2ParticleGroup* group, ParticleListNode* nodeBuffer);
917  void MergeZombieParticleListNodes(
918  const b2ParticleGroup* group, ParticleListNode* nodeBuffer,
919  ParticleListNode* survivingList) const;
920  static void MergeParticleListAndNode(
921  ParticleListNode* list, ParticleListNode* node);
922  void CreateParticleGroupsFromParticleList(
923  const b2ParticleGroup* group, ParticleListNode* nodeBuffer,
924  const ParticleListNode* survivingList);
925  void UpdatePairsAndTriadsWithParticleList(
926  const b2ParticleGroup* group, const ParticleListNode* nodeBuffer);
927 
928  void ComputeDepth();
929 
930  InsideBoundsEnumerator GetInsideBoundsEnumerator(const b2AABB& aabb) const;
931 
932  void UpdateAllParticleFlags();
933  void UpdateAllGroupFlags();
934  void AddContact(int32 a, int32 b,
935  b2GrowableBuffer<b2ParticleContact>& contacts) const;
936  void FindContacts_Reference(
937  b2GrowableBuffer<b2ParticleContact>& contacts) const;
938  void ReorderForFindContact(FindContactInput* reordered,
939  int alignedCount) const;
940  void GatherChecksOneParticle(
941  const uint32 bound,
942  const int startIndex,
943  const int particleIndex,
944  int* nextUncheckedIndex,
945  b2GrowableBuffer<FindContactCheck>& checks) const;
946  void GatherChecks(b2GrowableBuffer<FindContactCheck>& checks) const;
947  void FindContacts_Simd(
948  b2GrowableBuffer<b2ParticleContact>& contacts) const;
949  void FindContacts(
950  b2GrowableBuffer<b2ParticleContact>& contacts) const;
951  static void UpdateProxyTags(
952  const uint32* const tags,
953  b2GrowableBuffer<Proxy>& proxies);
954  static bool ProxyBufferHasIndex(
955  int32 index, const Proxy* const a, int count);
956  static int NumProxiesWithSameTag(
957  const Proxy* const a, const Proxy* const b, int count);
958  static bool AreProxyBuffersTheSame(const b2GrowableBuffer<Proxy>& a,
959  const b2GrowableBuffer<Proxy>& b);
960  void UpdateProxies_Reference(b2GrowableBuffer<Proxy>& proxies) const;
961  void UpdateProxies_Simd(b2GrowableBuffer<Proxy>& proxies) const;
962  void UpdateProxies(b2GrowableBuffer<Proxy>& proxies) const;
963  void SortProxies(b2GrowableBuffer<Proxy>& proxies) const;
964  void FilterContacts(b2GrowableBuffer<b2ParticleContact>& contacts);
965  void NotifyContactListenerPreContact(
966  b2ParticlePairSet* particlePairs) const;
967  void NotifyContactListenerPostContact(b2ParticlePairSet& particlePairs);
968  void UpdateContacts(bool exceptZombie);
969  void NotifyBodyContactListenerPreContact(
970  FixtureParticleSet* fixtureSet) const;
971  void NotifyBodyContactListenerPostContact(FixtureParticleSet& fixtureSet);
972  void UpdateBodyContacts();
973 
974  void Solve(const b2TimeStep& step);
975  void SolveCollision(const b2TimeStep& step);
976  void LimitVelocity(const b2TimeStep& step);
977  void SolveGravity(const b2TimeStep& step);
978  void SolveBarrier(const b2TimeStep& step);
979  void SolveStaticPressure(const b2TimeStep& step);
980  void ComputeWeight();
981  void SolvePressure(const b2TimeStep& step);
982  void SolveDamping(const b2TimeStep& step);
983  void SolveRigidDamping();
984  void SolveExtraDamping();
985  void SolveWall();
986  void SolveRigid(const b2TimeStep& step);
987  void SolveElastic(const b2TimeStep& step);
988  void SolveSpring(const b2TimeStep& step);
989  void SolveTensile(const b2TimeStep& step);
990  void SolveViscous();
991  void SolveRepulsive(const b2TimeStep& step);
992  void SolvePowder(const b2TimeStep& step);
993  void SolveSolid(const b2TimeStep& step);
994  void SolveForce(const b2TimeStep& step);
995  void SolveColorMixing();
996  void SolveZombie();
999  void SolveLifetimes(const b2TimeStep& step);
1000  void RotateBuffer(int32 start, int32 mid, int32 end);
1001 
1002  float32 GetCriticalVelocity(const b2TimeStep& step) const;
1003  float32 GetCriticalVelocitySquared(const b2TimeStep& step) const;
1004  float32 GetCriticalPressure(const b2TimeStep& step) const;
1005  float32 GetParticleStride() const;
1006  float32 GetParticleMass() const;
1007  float32 GetParticleInvMass() const;
1008 
1009  // Get the world's contact filter if any particles with the
1010  // b2_contactFilterParticle flag are present in the system.
1011  b2ContactFilter* GetFixtureContactFilter() const;
1012 
1013  // Get the world's contact filter if any particles with the
1014  // b2_particleContactFilterParticle flag are present in the system.
1015  b2ContactFilter* GetParticleContactFilter() const;
1016 
1017  // Get the world's contact listener if any particles with the
1018  // b2_fixtureContactListenerParticle flag are present in the system.
1019  b2ContactListener* GetFixtureContactListener() const;
1020 
1021  // Get the world's contact listener if any particles with the
1022  // b2_particleContactListenerParticle flag are present in the system.
1023  b2ContactListener* GetParticleContactListener() const;
1024 
1025  template <typename T> void SetUserOverridableBuffer(
1026  UserOverridableBuffer<T>* buffer, T* newBufferData, int32 newCapacity);
1027 
1028  void SetGroupFlags(b2ParticleGroup* group, uint32 flags);
1029 
1030  void RemoveSpuriousBodyContacts();
1031  static bool BodyContactCompare(const b2ParticleBodyContact& lhs,
1032  const b2ParticleBodyContact& rhs);
1033 
1034  void DetectStuckParticle(int32 particle);
1035 
1037  bool ValidateParticleIndex(const int32 index) const;
1038 
1040  int32 GetQuantizedTimeElapsed() const;
1042  int64 LifetimeToExpirationTime(const float32 lifetime) const;
1043 
1044  bool ForceCanBeApplied(uint32 flags) const;
1045  void PrepareForceBuffer();
1046 
1047  bool IsRigidGroup(b2ParticleGroup *group) const;
1048  b2Vec2 GetLinearVelocity(
1049  b2ParticleGroup *group, int32 particleIndex,
1050  const b2Vec2 &point) const;
1051  void InitDampingParameter(
1052  float32* invMass, float32* invInertia, float32* tangentDistance,
1053  float32 mass, float32 inertia, const b2Vec2& center,
1054  const b2Vec2& point, const b2Vec2& normal) const;
1055  void InitDampingParameterWithRigidGroupOrParticle(
1056  float32* invMass, float32* invInertia, float32* tangentDistance,
1057  bool isRigidGroup, b2ParticleGroup* group, int32 particleIndex,
1058  const b2Vec2& point, const b2Vec2& normal) const;
1059  float32 ComputeDampingImpulse(
1060  float32 invMassA, float32 invInertiaA, float32 tangentDistanceA,
1061  float32 invMassB, float32 invInertiaB, float32 tangentDistanceB,
1062  float32 normalVelocity) const;
1063  void ApplyDamping(
1064  float32 invMass, float32 invInertia, float32 tangentDistance,
1065  bool isRigidGroup, b2ParticleGroup* group, int32 particleIndex,
1066  float32 impulse, const b2Vec2& normal);
1067 
1068  bool m_paused;
1069  int32 m_timestamp;
1070  int32 m_allParticleFlags;
1071  bool m_needsUpdateAllParticleFlags;
1072  int32 m_allGroupFlags;
1073  bool m_needsUpdateAllGroupFlags;
1074  bool m_hasForce;
1075  int32 m_iterationIndex;
1076  float32 m_inverseDensity;
1077  float32 m_particleDiameter;
1078  float32 m_inverseDiameter;
1079  float32 m_squaredDiameter;
1080 
1081  int32 m_count;
1082  int32 m_internalAllocatedCapacity;
1084  b2SlabAllocator<b2ParticleHandle> m_handleAllocator;
1086  UserOverridableBuffer<b2ParticleHandle*> m_handleIndexBuffer;
1087  UserOverridableBuffer<uint32> m_flagsBuffer;
1088  UserOverridableBuffer<b2Vec2> m_positionBuffer;
1089  UserOverridableBuffer<b2Vec2> m_velocityBuffer;
1090  b2Vec2* m_forceBuffer;
1093  float32* m_weightBuffer;
1098  float32* m_staticPressureBuffer;
1101  float32* m_accumulationBuffer;
1106  b2Vec2* m_accumulation2Buffer;
1111  float32* m_depthBuffer;
1112  UserOverridableBuffer<b2ParticleColor> m_colorBuffer;
1113  b2ParticleGroup** m_groupBuffer;
1114  UserOverridableBuffer<void*> m_userDataBuffer;
1115 
1117  int32 m_stuckThreshold;
1118  UserOverridableBuffer<int32> m_lastBodyContactStepBuffer;
1119  UserOverridableBuffer<int32> m_bodyContactCountBuffer;
1120  UserOverridableBuffer<int32> m_consecutiveContactStepsBuffer;
1121  b2GrowableBuffer<int32> m_stuckParticleBuffer;
1122  b2GrowableBuffer<Proxy> m_proxyBuffer;
1123  b2GrowableBuffer<b2ParticleContact> m_contactBuffer;
1124  b2GrowableBuffer<b2ParticleBodyContact> m_bodyContactBuffer;
1125  b2GrowableBuffer<b2ParticlePair> m_pairBuffer;
1126  b2GrowableBuffer<b2ParticleTriad> m_triadBuffer;
1127 
1131  UserOverridableBuffer<int32> m_expirationTimeBuffer;
1133  UserOverridableBuffer<int32> m_indexByExpirationTimeBuffer;
1136  int64 m_timeElapsed;
1139  bool m_expirationTimeBufferRequiresSorting;
1140 
1141  int32 m_groupCount;
1142  b2ParticleGroup* m_groupList;
1143 
1144  b2ParticleSystemDef m_def;
1145 
1146  b2World* m_world;
1147  b2ParticleSystem* m_prev;
1148  b2ParticleSystem* m_next;
1149 };
1150 
1151 inline void b2ParticleContact::SetIndices(int32 a, int32 b)
1152 {
1153  b2Assert(a <= b2_maxParticleIndex && b <= b2_maxParticleIndex);
1154  indexA = (b2ParticleIndex)a;
1155  indexB = (b2ParticleIndex)b;
1156 }
1157 
1158 
1159 inline bool b2ParticleContact::operator==(
1160  const b2ParticleContact& rhs) const
1161 {
1162  return indexA == rhs.indexA
1163  && indexB == rhs.indexB
1164  && flags == rhs.flags
1165  && weight == rhs.weight
1166  && normal == rhs.normal;
1167 }
1168 
1169 // The reciprocal sqrt function differs between SIMD and non-SIMD, but they
1170 // should create approximately equal results.
1171 inline bool b2ParticleContact::ApproximatelyEqual(
1172  const b2ParticleContact& rhs) const
1173 {
1174  static const float MAX_WEIGHT_DIFF = 0.01f; // Weight 0 ~ 1, so about 1%
1175  static const float MAX_NORMAL_DIFF = 0.01f; // Normal length = 1, so 1%
1176  return indexA == rhs.indexA
1177  && indexB == rhs.indexB
1178  && flags == rhs.flags
1179  && b2Abs(weight - rhs.weight) < MAX_WEIGHT_DIFF
1180  && (normal - rhs.normal).Length() < MAX_NORMAL_DIFF;
1181 }
1182 
1184 {
1185  return m_groupList;
1186 }
1187 
1189 {
1190  return m_groupList;
1191 }
1192 
1194 {
1195  return m_groupCount;
1196 }
1197 
1199 {
1200  return m_count;
1201 }
1202 
1203 inline void b2ParticleSystem::SetPaused(bool paused)
1204 {
1205  m_paused = paused;
1206 }
1207 
1208 inline bool b2ParticleSystem::GetPaused() const
1209 {
1210  return m_paused;
1211 }
1212 
1214 {
1215  return m_contactBuffer.Data();
1216 }
1217 
1218 inline int32 b2ParticleSystem::GetContactCount() const
1219 {
1220  return m_contactBuffer.GetCount();
1221 }
1222 
1224 {
1225  return m_bodyContactBuffer.Data();
1226 }
1227 
1228 inline int32 b2ParticleSystem::GetBodyContactCount() const
1229 {
1230  return m_bodyContactBuffer.GetCount();
1231 }
1232 
1234 {
1235  return m_pairBuffer.Data();
1236 }
1237 
1238 inline int32 b2ParticleSystem::GetPairCount() const
1239 {
1240  return m_pairBuffer.GetCount();
1241 }
1242 
1244 {
1245  return m_triadBuffer.Data();
1246 }
1247 
1248 inline int32 b2ParticleSystem::GetTriadCount() const
1249 {
1250  return m_triadBuffer.GetCount();
1251 }
1252 
1254 {
1255  return m_next;
1256 }
1257 
1258 inline const b2ParticleSystem* b2ParticleSystem::GetNext() const
1259 {
1260  return m_next;
1261 }
1262 
1263 inline const int32* b2ParticleSystem::GetStuckCandidates() const
1264 {
1265  return m_stuckParticleBuffer.Data();
1266 }
1267 
1269 {
1270  return m_stuckParticleBuffer.GetCount();
1271 }
1272 
1274 {
1275  m_def.strictContactCheck = enabled;
1276 }
1277 
1279 {
1280  return m_def.strictContactCheck;
1281 }
1282 
1283 inline void b2ParticleSystem::SetRadius(float32 radius)
1284 {
1285  m_particleDiameter = 2 * radius;
1286  m_squaredDiameter = m_particleDiameter * m_particleDiameter;
1287  m_inverseDiameter = 1 / m_particleDiameter;
1288 }
1289 
1290 inline void b2ParticleSystem::SetDensity(float32 density)
1291 {
1292  m_def.density = density;
1293  m_inverseDensity = 1 / m_def.density;
1294 }
1295 
1296 inline float32 b2ParticleSystem::GetDensity() const
1297 {
1298  return m_def.density;
1299 }
1300 
1301 inline void b2ParticleSystem::SetGravityScale(float32 gravityScale)
1302 {
1303  m_def.gravityScale = gravityScale;
1304 }
1305 
1307 {
1308  return m_def.gravityScale;
1309 }
1310 
1311 inline void b2ParticleSystem::SetDamping(float32 damping)
1312 {
1313  m_def.dampingStrength = damping;
1314 }
1315 
1316 inline float32 b2ParticleSystem::GetDamping() const
1317 {
1318  return m_def.dampingStrength;
1319 }
1320 
1322 {
1323  m_def.staticPressureIterations = iterations;
1324 }
1325 
1327 {
1328  return m_def.staticPressureIterations;
1329 }
1330 
1331 inline float32 b2ParticleSystem::GetRadius() const
1332 {
1333  return m_particleDiameter / 2;
1334 }
1335 
1336 inline float32 b2ParticleSystem::GetCriticalVelocity(const b2TimeStep& step) const
1337 {
1338  return m_particleDiameter * step.inv_dt;
1339 }
1340 
1341 inline float32 b2ParticleSystem::GetCriticalVelocitySquared(
1342  const b2TimeStep& step) const
1343 {
1344  float32 velocity = GetCriticalVelocity(step);
1345  return velocity * velocity;
1346 }
1347 
1348 inline float32 b2ParticleSystem::GetCriticalPressure(const b2TimeStep& step) const
1349 {
1350  return m_def.density * GetCriticalVelocitySquared(step);
1351 }
1352 
1353 inline float32 b2ParticleSystem::GetParticleStride() const
1354 {
1355  return b2_particleStride * m_particleDiameter;
1356 }
1357 
1358 inline float32 b2ParticleSystem::GetParticleMass() const
1359 {
1360  float32 stride = GetParticleStride();
1361  return m_def.density * stride * stride;
1362 }
1363 
1364 inline float32 b2ParticleSystem::GetParticleInvMass() const
1365 {
1366  // mass = density * stride^2, so we take the inverse of this.
1367  float32 inverseStride = m_inverseDiameter * (1.0f / b2_particleStride);
1368  return m_inverseDensity * inverseStride * inverseStride;
1369 }
1370 
1372 {
1373  return m_positionBuffer.data;
1374 }
1375 
1377 {
1378  return m_velocityBuffer.data;
1379 }
1380 
1382 {
1383  return m_weightBuffer;
1384 }
1385 
1387 {
1388  return m_def.maxCount;
1389 }
1390 
1392 {
1393  b2Assert(m_count <= count);
1394  m_def.maxCount = count;
1395 }
1396 
1398 {
1399  return m_allParticleFlags;
1400 }
1401 
1403 {
1404  return m_allGroupFlags;
1405 }
1406 
1407 inline const uint32* b2ParticleSystem::GetFlagsBuffer() const
1408 {
1409  return m_flagsBuffer.data;
1410 }
1411 
1412 inline const b2Vec2* b2ParticleSystem::GetPositionBuffer() const
1413 {
1414  return m_positionBuffer.data;
1415 }
1416 
1417 inline const b2Vec2* b2ParticleSystem::GetVelocityBuffer() const
1418 {
1419  return m_velocityBuffer.data;
1420 }
1421 
1423 {
1424  return ((b2ParticleSystem*) this)->GetColorBuffer();
1425 }
1426 
1427 inline const b2ParticleGroup* const* b2ParticleSystem::GetGroupBuffer() const
1428 {
1429  return m_groupBuffer;
1430 }
1431 
1432 inline const float32* b2ParticleSystem::GetWeightBuffer() const
1433 {
1434  return m_weightBuffer;
1435 }
1436 
1437 inline void* const* b2ParticleSystem::GetUserDataBuffer() const
1438 {
1439  return ((b2ParticleSystem*) this)->GetUserDataBuffer();
1440 }
1441 
1443 {
1444  return m_groupBuffer;
1445 }
1446 
1447 inline uint32 b2ParticleSystem::GetParticleFlags(int32 index)
1448 {
1449  return GetFlagsBuffer()[index];
1450 }
1451 
1452 inline bool b2ParticleSystem::ValidateParticleIndex(const int32 index) const
1453 {
1454  return index >= 0 && index < GetParticleCount() &&
1455  index != b2_invalidParticleIndex;
1456 }
1457 
1459 {
1460  return m_def.destroyByAge;
1461 }
1462 
1464  const b2Vec2& impulse)
1465 {
1466  ApplyLinearImpulse(index, index + 1, impulse);
1467 }
1468 
1469 
1470 // Note: These functions must go in the header so the unit tests will compile
1471 // them. b2ParticleSystem.cpp does not compile with this #define.
1472 #if LIQUIDFUN_EXTERNAL_LANGUAGE_API
1473 
1474 inline void b2ParticleSystem::SetParticleVelocity(int32 index,
1475  float32 vx,
1476  float32 vy)
1477 {
1478  b2Vec2& v = GetVelocityBuffer()[index];
1479  v.x = vx;
1480  v.y = vy;
1481 }
1482 
1483 inline float b2ParticleSystem::GetParticlePositionX(int32 index) const
1484 {
1485  return GetPositionBuffer()[index].x;
1486 }
1487 
1488 inline float b2ParticleSystem::GetParticlePositionY(int32 index) const
1489 {
1490  return GetPositionBuffer()[index].y;
1491 }
1492 
1493 inline int b2ParticleSystem::CopyPositionBuffer(int startIndex,
1494  int numParticles,
1495  void* outBuf,
1496  int size) const
1497 {
1498  int copySize = numParticles * sizeof(b2Vec2);
1499  void* inBufWithOffset = (void*) (GetPositionBuffer() + startIndex);
1500  return CopyBuffer(startIndex, numParticles, inBufWithOffset, outBuf, size,
1501  copySize);
1502 }
1503 
1504 inline int b2ParticleSystem::CopyColorBuffer(int startIndex,
1505  int numParticles,
1506  void* outBuf,
1507  int size) const
1508 {
1509  int copySize = numParticles * sizeof(b2ParticleColor);
1510  void* inBufWithOffset = (void*) (GetColorBuffer() + startIndex);
1511  return CopyBuffer(startIndex, numParticles, inBufWithOffset, outBuf, size,
1512  copySize);
1513 }
1514 
1515 inline int b2ParticleSystem::CopyWeightBuffer(int startIndex,
1516  int numParticles,
1517  void* outBuf,
1518  int size) const
1519 {
1520  int copySize = numParticles * sizeof(float32);
1521  void* inBufWithOffset = (void*) (GetWeightBuffer() + startIndex);
1522  return CopyBuffer(startIndex, numParticles, inBufWithOffset, outBuf, size,
1523  copySize);
1524 }
1525 
1526 inline int b2ParticleSystem::CopyBuffer(int startIndex, int numParticles,
1527  void* inBufWithOffset, void* outBuf,
1528  int outBufSize, int copySize) const
1529 {
1530  b2ExceptionType exception = IsBufCopyValid(startIndex, numParticles,
1531  copySize, outBufSize);
1532  if (exception != b2_noExceptions)
1533  {
1534  return exception;
1535  }
1536 
1537  memcpy(outBuf, inBufWithOffset, copySize);
1538  return b2_noExceptions;
1539 }
1540 
1541 #endif // LIQUIDFUN_EXTERNAL_LANGUAGE_API
1542 
1543 #endif
1544 
Definition: b2Math.h:411
float32 gravityScale
Definition: b2ParticleSystem.h:193
const int32 * GetExpirationTimeBuffer()
Definition: b2ParticleSystem.cpp:4274
float32 ExpirationTimeToLifetime(const int32 expirationTime) const
Definition: b2ParticleSystem.cpp:4256
Prevents other particles from leaking.
Definition: b2Particle.h:54
void SetPaused(bool paused)
Definition: b2ParticleSystem.h:1203
float32 radius
Particles behave as circles with this radius. In Box2D units.
Definition: b2ParticleSystem.h:196
Connection between two particles.
Definition: b2ParticleSystem.h:121
uint32 flags
The logical sum of the particle flags. See the b2ParticleFlag enum.
Definition: b2ParticleSystem.h:143
void ApplyForce(int32 firstIndex, int32 lastIndex, const b2Vec2 &force)
Definition: b2ParticleSystem.cpp:4434
const uint32 * GetFlagsBuffer() const
Definition: b2ParticleSystem.h:1407
b2Vec2 * GetVelocityBuffer()
Definition: b2ParticleSystem.h:1376
Definition: b2ParticleSystem.h:153
void ParticleApplyLinearImpulse(int32 index, const b2Vec2 &impulse)
Definition: b2ParticleSystem.h:1463
float32 repulsiveStrength
Definition: b2ParticleSystem.h:237
float32 GetRadius() const
Get the particle radius.
Definition: b2ParticleSystem.h:1331
float32 lifetimeGranularity
Definition: b2ParticleSystem.h:277
void SetDensity(float32 density)
Definition: b2ParticleSystem.h:1290
float32 density
Definition: b2ParticleSystem.h:189
const b2ParticleHandle * GetParticleHandleFromIndex(const int32 index)
Retrieve a handle to the particle at the specified index.
Definition: b2ParticleSystem.cpp:748
Definition: b2ParticleGroup.h:54
int32 maxCount
Definition: b2ParticleSystem.h:202
float32 ComputeCollisionEnergy() const
Compute the kinetic energy that can be lost by damping force.
Definition: b2ParticleSystem.cpp:4581
Definition: b2WorldCallbacks.h:241
uint32 flags
The logical sum of the particle flags. See the b2ParticleFlag enum.
Definition: b2ParticleSystem.h:127
b2ParticleColor * GetColorBuffer()
Definition: b2ParticleSystem.cpp:558
float32 * GetWeightBuffer()
Definition: b2ParticleSystem.h:1381
void RayCast(b2RayCastCallback *callback, const b2Vec2 &point1, const b2Vec2 &point2) const
Definition: b2ParticleSystem.cpp:4527
void SetParticleLifetime(const int32 index, const float32 lifetime)
Definition: b2ParticleSystem.cpp:4220
b2ParticleGroup * GetParticleGroupList()
Definition: b2ParticleSystem.h:1183
uint32 GetAllGroupFlags() const
Get all existing particle group flags.
Definition: b2ParticleSystem.h:1402
float32 weight
Weight of the contact. A value between 0.0f and 1.0f.
Definition: b2ParticleSystem.h:111
Definition: b2StackAllocator.h:37
Definition: b2World.h:44
Definition: b2ParticleSystem.h:281
Definition: b2WorldCallbacks.h:74
int32 staticPressureIterations
Definition: b2ParticleSystem.h:259
bool strictContactCheck
Definition: b2ParticleSystem.h:185
b2ParticleGroup * CreateParticleGroup(const b2ParticleGroupDef &def)
Definition: b2ParticleSystem.cpp:1043
int32 GetStuckCandidateCount() const
Get the number of stuck particle candidates from the last step.
Definition: b2ParticleSystem.h:1268
void ComputeAABB(b2AABB *const aabb) const
Definition: b2ParticleSystem.cpp:2336
Definition: b2WorldCallbacks.h:128
uint32 GetParticleFlags(const int32 index)
Get flags for a particle. See the b2ParticleFlag enum.
Definition: b2ParticleSystem.h:1447
Definition: b2BlockAllocator.h:36
float32 GetParticleLifetime(const int32 index)
Definition: b2ParticleSystem.cpp:4266
float32 distance
The initial distance of the particles.
Definition: b2ParticleSystem.h:133
Definition: b2Shape.h:43
void QueryShapeAABB(b2QueryCallback *callback, const b2Shape &shape, const b2Transform &xf) const
Definition: b2ParticleSystem.cpp:4518
b2Vec2 pa
Values used for calculation.
Definition: b2ParticleSystem.h:149
With restitution from deformation.
Definition: b2Particle.h:42
bool GetStrictContactCheck() const
Get the status of the strict contact check.
Definition: b2ParticleSystem.h:1278
float32 colorMixingStrength
Definition: b2ParticleSystem.h:264
float32 powderStrength
Definition: b2ParticleSystem.h:241
bool GetDestructionByAge() const
Definition: b2ParticleSystem.h:1458
int32 index
Index of the particle making contact.
Definition: b2ParticleSystem.h:102
void SetMaxParticleCount(int32 count)
Definition: b2ParticleSystem.h:1391
void ParticleApplyForce(int32 index, const b2Vec2 &force)
Definition: b2ParticleSystem.cpp:4462
float32 staticPressureRelaxation
Definition: b2ParticleSystem.h:255
Definition: b2ParticleAssembly.h:27
Definition: b2Particle.h:272
b2Vec2 normal
The normalized direction from the particle to the body.
Definition: b2ParticleSystem.h:114
Small color object for each particle.
Definition: b2Particle.h:81
Without isotropic pressure.
Definition: b2Particle.h:46
void SetParticleFlags(int32 index, uint32 flags)
Set flags for a particle. See the b2ParticleFlag enum.
Definition: b2ParticleSystem.cpp:4364
Definition: b2ParticleAssembly.h:33
float32 strength
The strength of cohesion among the particles.
Definition: b2ParticleSystem.h:130
float32 pressureStrength
Definition: b2ParticleSystem.h:206
uint32 GetAllParticleFlags() const
Get all existing particle flags.
Definition: b2ParticleSystem.h:1397
float32 ejectionStrength
Definition: b2ParticleSystem.h:245
b2Fixture * fixture
The specific fixture making contact.
Definition: b2ParticleSystem.h:108
float32 mass
The effective mass used in calculating force.
Definition: b2ParticleSystem.h:117
Connection between three particles.
Definition: b2ParticleSystem.h:137
const int32 * GetStuckCandidates() const
Definition: b2ParticleSystem.h:1263
void SetDamping(float32 damping)
Definition: b2ParticleSystem.h:1311
int32 GetParticleCount() const
Get the number of particles.
Definition: b2ParticleSystem.h:1198
void ** GetUserDataBuffer()
Definition: b2ParticleSystem.cpp:564
With surface tension.
Definition: b2Particle.h:48
A group of particles. b2ParticleGroup::CreateParticleGroup creates these.
Definition: b2ParticleGroup.h:172
float32 dampingStrength
Definition: b2ParticleSystem.h:210
An axis aligned bounding box.
Definition: b2Collision.h:162
int32 DestroyParticlesInShape(const b2Shape &shape, const b2Transform &xf)
Definition: b2ParticleSystem.h:331
void SetFlagsBuffer(uint32 *buffer, int32 capacity)
Definition: b2ParticleSystem.cpp:4336
float32 GetGravityScale() const
Get the particle gravity scale.
Definition: b2ParticleSystem.h:1306
const b2ParticleBodyContact * GetBodyContacts() const
Definition: b2ParticleSystem.h:1223
This is an internal structure.
Definition: b2TimeStep.h:39
b2Vec2 * GetPositionBuffer()
Definition: b2ParticleSystem.h:1371
Less compressibility.
Definition: b2Particle.h:56
int32 GetParticleGroupCount() const
Get the number of particle groups.
Definition: b2ParticleSystem.h:1193
float32 viscousStrength
Definition: b2ParticleSystem.h:222
int32 GetMaxParticleCount() const
Get the maximum number of particles.
Definition: b2ParticleSystem.h:1386
bool destroyByAge
Definition: b2ParticleSystem.h:269
void DestroyOldestParticle(const int32 index, const bool callDestructionListener)
Definition: b2ParticleSystem.cpp:779
Definition: b2ParticleSystem.h:99
void SetRadius(float32 radius)
Definition: b2ParticleSystem.h:1283
int32 GetStaticPressureIterations() const
Get the number of iterations for static pressure of particles.
Definition: b2ParticleSystem.h:1326
const b2ParticleTriad * GetTriads() const
Definition: b2ParticleSystem.h:1243
#define b2_particleStride
The default distance between particles, multiplied by the particle diameter.
Definition: b2Settings.h:177
A rigid body. These are created via b2World::CreateBody.
Definition: b2Body.h:132
int32 indexA
Indices of the respective particles making pair.
Definition: b2ParticleSystem.h:124
bool GetPaused() const
Definition: b2ParticleSystem.h:1208
void SetStaticPressureIterations(int32 iterations)
Definition: b2ParticleSystem.h:1321
float32 surfaceTensionNormalStrength
Definition: b2ParticleSystem.h:231
void SetDestructionByAge(const bool enable)
Definition: b2ParticleSystem.cpp:4301
With restitution from stretching.
Definition: b2Particle.h:40
void SetStuckThreshold(int32 iterations)
Definition: b2ParticleSystem.cpp:4600
float32 staticPressureStrength
Definition: b2ParticleSystem.h:251
b2ParticleGroup *const * GetGroupBuffer()
Definition: b2ParticleSystem.h:1442
b2Body * body
The body making contact.
Definition: b2ParticleSystem.h:105
int32 CreateParticle(const b2ParticleDef &def)
Definition: b2ParticleSystem.cpp:637
float32 springStrength
Definition: b2ParticleSystem.h:218
Definition: b2ParticleSystem.h:53
A 2D column vector.
Definition: b2Math.h:56
void JoinParticleGroups(b2ParticleGroup *groupA, b2ParticleGroup *groupB)
Definition: b2ParticleSystem.cpp:1111
void SplitParticleGroup(b2ParticleGroup *group)
Definition: b2ParticleSystem.cpp:1163
#define b2_invalidParticleIndex
NEON SIMD requires 16-bit particle indices.
Definition: b2Settings.h:168
int32 indexA
Indices of the respective particles making triad.
Definition: b2ParticleSystem.h:140
void ApplyLinearImpulse(int32 firstIndex, int32 lastIndex, const b2Vec2 &impulse)
Definition: b2ParticleSystem.cpp:4472
float32 strength
The strength of cohesion among the particles.
Definition: b2ParticleSystem.h:146
float32 surfaceTensionPressureStrength
Definition: b2ParticleSystem.h:226
float32 GetDamping() const
Get damping for particles.
Definition: b2ParticleSystem.h:1316
const b2ParticlePair * GetPairs() const
Definition: b2ParticleSystem.h:1233
float32 elasticStrength
Definition: b2ParticleSystem.h:214
float32 GetDensity() const
Get the particle density.
Definition: b2ParticleSystem.h:1296
Definition: b2WorldCallbacks.h:208
void SetStrictContactCheck(bool enabled)
Definition: b2ParticleSystem.h:1273
b2ParticleSystem * GetNext()
Get the next particle-system in the world's particle-system list.
Definition: b2ParticleSystem.h:1253
void DestroyParticle(int32 index)
Definition: b2ParticleSystem.h:300
void QueryAABB(b2QueryCallback *callback, const b2AABB &aabb) const
Definition: b2ParticleSystem.cpp:4484
const b2ParticleContact * GetContacts() const
Definition: b2ParticleSystem.h:1213
const int32 * GetIndexByExpirationTimeBuffer()
Definition: b2ParticleSystem.cpp:4286
Definition: b2Particle.h:330
void SetGravityScale(float32 gravityScale)
Definition: b2ParticleSystem.h:1301
Definition: b2Fixture.h:108