Adding Particle::_mass and correct elastic collisions between particles

This commit is contained in:
Andrew Meadows 2014-01-10 11:37:01 -08:00
parent 6f21592ebd
commit 71e5de8420
3 changed files with 47 additions and 29 deletions

View file

@ -54,6 +54,7 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3
_position = position; _position = position;
_radius = radius; _radius = radius;
_mass = 1.0f;
memcpy(_color, color, sizeof(_color)); memcpy(_color, color, sizeof(_color));
_velocity = velocity; _velocity = velocity;
_damping = damping; _damping = damping;
@ -63,6 +64,11 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3
_shouldDie = false; _shouldDie = false;
} }
void Particle::setMass(float value) {
if (value > 0.0f) {
_mass = value;
}
}
bool Particle::appendParticleData(OctreePacketData* packetData) const { bool Particle::appendParticleData(OctreePacketData* packetData) const {

View file

@ -67,6 +67,7 @@ public:
const rgbColor& getColor() const { return _color; } const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
float getRadius() const { return _radius; } float getRadius() const { return _radius; }
float getMass() const { return _mass; }
const glm::vec3& getVelocity() const { return _velocity; } const glm::vec3& getVelocity() const { return _velocity; }
const glm::vec3& getGravity() const { return _gravity; } const glm::vec3& getGravity() const { return _gravity; }
bool getInHand() const { return _inHand; } bool getInHand() const { return _inHand; }
@ -96,6 +97,7 @@ public:
_color[BLUE_INDEX] = value.blue; _color[BLUE_INDEX] = value.blue;
} }
void setRadius(float value) { _radius = value; } void setRadius(float value) { _radius = value; }
void setMass(float value);
void setGravity(const glm::vec3& value) { _gravity = value; } void setGravity(const glm::vec3& value) { _gravity = value; }
void setInHand(bool inHand) { _inHand = inHand; } void setInHand(bool inHand) { _inHand = inHand; }
void setDamping(float value) { _damping = value; } void setDamping(float value) { _damping = value; }
@ -146,6 +148,7 @@ protected:
glm::vec3 _position; glm::vec3 _position;
rgbColor _color; rgbColor _color;
float _radius; float _radius;
float _mass;
glm::vec3 _velocity; glm::vec3 _velocity;
uint32_t _id; uint32_t _id;
static uint32_t _nextID; static uint32_t _nextID;

View file

@ -87,41 +87,50 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
} }
} }
void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA) {
glm::vec3 center = particle->getPosition() * static_cast<float>(TREE_SCALE); glm::vec3 center = particleA->getPosition() * (float)TREE_SCALE;
float radius = particle->getRadius() * static_cast<float>(TREE_SCALE); float radius = particleA->getRadius() * (float)TREE_SCALE;
const float ELASTICITY = 1.4f; const float ELASTICITY = 0.4f;
const float DAMPING = 0.0f; const float DAMPING = 0.0f;
const float COLLISION_FREQUENCY = 0.5f; const float COLLISION_FREQUENCY = 0.5f;
glm::vec3 penetration; glm::vec3 penetration;
Particle* penetratedParticle; Particle* particleB;
if (_particles->findSpherePenetration(center, radius, penetration, (void**)&penetratedParticle)) { if (_particles->findSpherePenetration(center, radius, penetration, (void**)&particleB)) {
// NOTE: 'penetration' is the depth that 'particleA' overlaps 'particleB'.
// That is, it points from A into B.
// let the particles run their collision scripts if they have them // Even if the particles overlap... when the particles are already moving appart
particle->collisionWithParticle(penetratedParticle); // we don't want to count this as a collision.
penetratedParticle->collisionWithParticle(particle); glm::vec3 relativeVelocity = particleA->getVelocity() - particleB->getVelocity();
if (glm::dot(relativeVelocity, penetration) > 0.0f) {
particleA->collisionWithParticle(particleB);
particleB->collisionWithParticle(particleA);
penetration /= static_cast<float>(TREE_SCALE); glm::vec3 axis = glm::normalize(penetration);
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY); glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
// apply a hard collision to both particles of half the penetration each // particles that are in hand are assigned an ureasonably large mass for collisions
// which effectively makes them immovable but allows the other ball to reflect correctly.
float particleShare, penetratedParticleShare; const float MAX_MASS = 1.0e6f;
if (particle->getInHand() && penetratedParticle->getInHand()) { float massA = (particleA->getInHand()) ? MAX_MASS : particleA->getMass();
particleShare = 0.5f; float massB = (particleB->getInHand()) ? MAX_MASS : particleB->getMass();
penetratedParticleShare = -0.5f; float totalMass = massA + massB;
} else if (particle->getInHand()) {
particleShare = 0.f; particleA->setVelocity(particleA->getVelocity() - axialVelocity * (2.0f * massB / totalMass));
penetratedParticleShare = -1.f;
} else if (penetratedParticle->getInHand()) { ParticleEditHandle particleEditHandle(_packetSender, _particles, particleA->getID());
particleShare = -1.f; particleEditHandle.updateParticle(particleA->getPosition(), particleA->getRadius(), particleA->getXColor(), particleA->getVelocity(),
penetratedParticleShare = 0.f; particleA->getGravity(), particleA->getDamping(), particleA->getInHand(), particleA->getScript());
} else {
particleShare = 0.5f; particleB->setVelocity(particleB->getVelocity() + axialVelocity * (2.0f * massA / totalMass));
penetratedParticleShare = -0.5f;
ParticleEditHandle penetratedparticleEditHandle(_packetSender, _particles, particleB->getID());
penetratedparticleEditHandle.updateParticle(particleB->getPosition(), particleB->getRadius(), particleB->getXColor(), particleB->getVelocity(),
particleB->getGravity(), particleB->getDamping(), particleB->getInHand(), particleB->getScript());
penetration /= (float)TREE_SCALE;
updateCollisionSound(particleA, penetration, COLLISION_FREQUENCY);
} }
applyHardCollision(particle, penetration * particleShare, ELASTICITY, DAMPING);
applyHardCollision(penetratedParticle, penetration * penetratedParticleShare, ELASTICITY, DAMPING);
} }
} }