principia/lib/Box2D/Particle/b2ParticleSystem.h

332 lines
9.6 KiB
C++

/*
* 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 <Box2D/Particle/b2Particle.h>
#include <Box2D/Dynamics/b2TimeStep.h>
/// 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 <typename T>
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 <typename T> T* ReallocateBuffer(T* buffer, int32 oldCapacity, int32 newCapacity);
template <typename T> T* ReallocateBuffer(T* buffer, int32 userSuppliedCapacity, int32 oldCapacity, int32 newCapacity, bool deferred);
template <typename T> T* ReallocateBuffer(ParticleBuffer<T>* buffer, int32 oldCapacity, int32 newCapacity, bool deferred);
template <typename T> 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 <typename T> void SetParticleBuffer(ParticleBuffer<T>* 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<uint32> m_flagsBuffer;
ParticleBuffer<b2Vec2> m_positionBuffer;
ParticleBuffer<b2Vec2> m_velocityBuffer;
float32* m_dataBuffer;
float32* m_accumulationBuffer; // temporary values
b2Vec2* m_accumulation2Buffer; // temporary vector values
float32* m_depthBuffer; // distance from the surface
ParticleBuffer<b2ParticleColor> m_colorBuffer;
b2ParticleGroup** m_groupBuffer;
ParticleBuffer<void*> 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