mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 09:57:13 +02:00
Adding Particle::_mass and correct elastic collisions between particles
This commit is contained in:
parent
6f21592ebd
commit
71e5de8420
3 changed files with 47 additions and 29 deletions
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue