/* * Copyright (c) 2013 Google, Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef B2_PARTICLb2_SYSTEM_H #define B2_PARTICLb2_SYSTEM_H #include #include /// You need not to directly access b2ParticleSystem. /// To access particle data, use functions in b2World or b2ParticleGroup. class b2World; class b2Body; class b2Shape; class b2ParticleGroup; class b2BlockAllocator; class b2StackAllocator; class b2QueryCallback; class b2RayCastCallback; struct b2ParticleGroupDef; struct b2Vec2; struct b2AABB; struct b2ParticleContact { ///Indices of the respective particles making contact. /// int32 indexA, indexB; ///The logical sum of the particle behaviors that have been set. /// uint32 flags; /// Weight of the contact. A value between 0.0f and 1.0f. /// float32 weight; ///The normalized direction from A to B. /// b2Vec2 normal; }; struct b2ParticleBodyContact { /// Index of the particle making contact. /// int32 index; /// The body making contact. /// b2Body* body; ///Weight of the contact. A value between 0.0f and 1.0f. /// float32 weight; /// The normalized direction from the particle to the body. /// b2Vec2 normal; /// The effective mass used in calculating force. /// float32 mass; }; class b2ParticleSystem { private: friend class b2World; friend class b2ParticleGroup; template struct ParticleBuffer { ParticleBuffer() { data = NULL; userSuppliedCapacity = 0; } T* data; int32 userSuppliedCapacity; }; /// Used for detecting particle contacts struct Proxy { int32 index; uint32 tag; friend inline bool operator<(const Proxy &a, const Proxy &b) { return a.tag < b.tag; } friend inline bool operator<(uint32 a, const Proxy &b) { return a < b.tag; } friend inline bool operator<(const Proxy &a, uint32 b) { return a.tag < b; } }; /// Connection between two particles struct Pair { int32 indexA, indexB; uint32 flags; float32 strength; float32 distance; }; /// Connection between three particles struct Triad { int32 indexA, indexB, indexC; uint32 flags; float32 strength; b2Vec2 pa, pb, pc; float32 ka, kb, kc, s; }; // Callback used with b2VoronoiDiagram. class CreateParticleGroupCallback { public: void operator()(int32 a, int32 b, int32 c) const; b2ParticleSystem* system; const b2ParticleGroupDef* def; int32 firstIndex; }; // Callback used with b2VoronoiDiagram. class JoinParticleGroupsCallback { public: void operator()(int32 a, int32 b, int32 c) const; b2ParticleSystem* system; b2ParticleGroup* groupA; b2ParticleGroup* groupB; }; /// All particle types that require creating pairs static const int32 k_pairFlags = b2_springParticle; /// All particle types that require creating triads static const int32 k_triadFlags = b2_elasticParticle; /// All particle types that require computing depth static const int32 k_noPressureFlags = b2_powderParticle; b2ParticleSystem(); ~b2ParticleSystem(); template T* ReallocateBuffer(T* buffer, int32 oldCapacity, int32 newCapacity); template T* ReallocateBuffer(T* buffer, int32 userSuppliedCapacity, int32 oldCapacity, int32 newCapacity, bool deferred); template T* ReallocateBuffer(ParticleBuffer* buffer, int32 oldCapacity, int32 newCapacity, bool deferred); template T* RequestParticleBuffer(T* buffer); int32 CreateParticle(const b2ParticleDef& def); void DestroyParticle(int32 index, bool callDestructionListener); // Destroy particles in the specified shape with the transform xf applied // optionally calling the destruction listener for particles that are // destroyed. int32 DestroyParticlesInShape(const b2Shape& shape, const b2Transform& xf, bool callDestructionListener); void DestroyParticlesInGroup(b2ParticleGroup* group, bool callDestructionListener); b2ParticleGroup* CreateParticleGroup(const b2ParticleGroupDef& def); void JoinParticleGroups(b2ParticleGroup* groupA, b2ParticleGroup* groupB); void DestroyParticleGroup(b2ParticleGroup* group); void ComputeDepthForGroup(b2ParticleGroup* group); void AddContact(int32 a, int32 b); void UpdateContacts(bool exceptZombie); void UpdateBodyContacts(); void Solve(const b2TimeStep& step); void SolveCollision(const b2TimeStep& step); void SolvePressure(const b2TimeStep& step); void SolveDamping(const b2TimeStep& step); void SolveWall(const b2TimeStep& step); void SolveRigid(const b2TimeStep& step); void SolveElastic(const b2TimeStep& step); void SolveSpring(const b2TimeStep& step); void SolveTensile(const b2TimeStep& step); void SolveViscous(const b2TimeStep& step); void SolvePowder(const b2TimeStep& step); void SolveSolid(const b2TimeStep& step); void SolveColorMixing(const b2TimeStep& step); void SolveZombie(); void RotateBuffer(int32 start, int32 mid, int32 end); void SetParticleRadius(float32 radius); float32 GetParticleRadius() const; void SetParticleDensity(float32 density); float32 GetParticleDensity() const; void SetParticleGravityScale(float32 gravityScale); float32 GetParticleGravityScale() const; void SetParticleDamping(float32 damping); float32 GetParticleDamping() const; float32 GetCriticalVelocity(const b2TimeStep& step) const; float32 GetCriticalVelocitySquared(const b2TimeStep& step) const; float32 GetCriticalPressure(const b2TimeStep& step) const; float32 GetParticleStride() const; float32 GetParticleMass() const; float32 GetParticleInvMass() const; b2ParticleGroup* GetParticleGroupList(); const b2ParticleGroup* GetParticleGroupList() const; int32 GetParticleGroupCount() const; int32 GetParticleCount() const; int32 GetParticleMaxCount() const; void SetParticleMaxCount(int32 count); uint32* GetParticleFlagsBuffer(); float32* GetParticleAccumulationBuffer(); b2Vec2* GetParticlePositionBuffer(); b2Vec2* GetParticleVelocityBuffer(); b2ParticleColor* GetParticleColorBuffer(); void** GetParticleUserDataBuffer(); const uint32* GetParticleFlagsBuffer() const; const b2Vec2* GetParticlePositionBuffer() const; const b2Vec2* GetParticleVelocityBuffer() const; const b2ParticleColor* GetParticleColorBuffer() const; const b2ParticleGroup* const* GetParticleGroupBuffer() const; void* const* GetParticleUserDataBuffer() const; template void SetParticleBuffer(ParticleBuffer* buffer, T* newBufferData, int32 newCapacity); void SetParticleFlagsBuffer(uint32* buffer, int32 capacity); void SetParticlePositionBuffer(b2Vec2* buffer, int32 capacity); void SetParticleVelocityBuffer(b2Vec2* buffer, int32 capacity); void SetParticleColorBuffer(b2ParticleColor* buffer, int32 capacity); b2ParticleGroup* const* GetParticleGroupBuffer(); void SetParticleUserDataBuffer(void** buffer, int32 capacity); void QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const; void RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const; float32 ComputeParticleCollisionEnergy() const; int32 m_timestamp; int32 m_allParticleFlags; int32 m_allGroupFlags; float32 m_density; float32 m_inverseDensity; float32 m_gravityScale; float32 m_particleDiameter; float32 m_inverseDiameter; float32 m_squaredDiameter; int32 m_count; int32 m_internalAllocatedCapacity; int32 m_maxCount; ParticleBuffer m_flagsBuffer; ParticleBuffer m_positionBuffer; ParticleBuffer m_velocityBuffer; float32* m_dataBuffer; float32* m_accumulationBuffer; // temporary values b2Vec2* m_accumulation2Buffer; // temporary vector values float32* m_depthBuffer; // distance from the surface ParticleBuffer m_colorBuffer; b2ParticleGroup** m_groupBuffer; ParticleBuffer m_userDataBuffer; int32 m_proxyCount; int32 m_proxyCapacity; Proxy* m_proxyBuffer; public: int32 m_contactCount; int32 m_contactCapacity; b2ParticleContact* m_contactBuffer; private: int32 m_bodyContactCount; int32 m_bodyContactCapacity; b2ParticleBodyContact* m_bodyContactBuffer; int32 m_pairCount; int32 m_pairCapacity; Pair* m_pairBuffer; int32 m_triadCount; int32 m_triadCapacity; Triad* m_triadBuffer; int32 m_groupCount; b2ParticleGroup* m_groupList; float32 m_pressureStrength; float32 m_dampingStrength; float32 m_elasticStrength; float32 m_springStrength; float32 m_viscousStrength; float32 m_surfaceTensionStrengthA; float32 m_surfaceTensionStrengthB; float32 m_powderStrength; float32 m_ejectionStrength; float32 m_colorMixingStrength; b2World* m_world; }; inline b2ParticleGroup* b2ParticleSystem::GetParticleGroupList() { return m_groupList; } inline const b2ParticleGroup* b2ParticleSystem::GetParticleGroupList() const { return m_groupList; } inline int32 b2ParticleSystem::GetParticleGroupCount() const { return m_groupCount; } inline int32 b2ParticleSystem::GetParticleCount() const { return m_count; } #endif