Moving applyHardCollision to the Particle class. Adding daming and elasticity to CollisionInfo.

This commit is contained in:
Andrew Meadows 2014-01-24 16:29:44 -08:00
parent 5cc2b029cf
commit 2f02ee0b31
5 changed files with 68 additions and 45 deletions

View file

@ -668,7 +668,50 @@ void Particle::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssiz
}
}
// HALTING_* params are determined using expected acceleration of gravity over some timescale.
// This is a HACK for particles that bounce in a 1.0 gravitational field and should eventually be made more universal.
const float HALTING_PARTICLE_PERIOD = 0.0167f; // ~1/60th of a second
const float HALTING_PARTICLE_SPEED = 9.8 * HALTING_PARTICLE_PERIOD / (float)(TREE_SCALE);
void Particle::applyHardCollision(const CollisionInfo& collisionInfo) {
//
// Update the particle in response to a hard collision. Position will be reset exactly
// to outside the colliding surface. Velocity will be modified according to elasticity.
//
// if elasticity = 0.0, collision is inelastic (vel normal to collision is lost)
// if elasticity = 1.0, collision is 100% elastic.
//
glm::vec3 position = getPosition();
glm::vec3 velocity = getVelocity();
const float EPSILON = 0.0f;
glm::vec3 relativeVelocity = collisionInfo._addedVelocity - velocity;
float velocityDotPenetration = glm::dot(relativeVelocity, collisionInfo._penetration);
if (velocityDotPenetration < EPSILON) {
// particle is moving into collision surface
//
// TODO: do something smarter here by comparing the mass of the particle vs that of the other thing
// (other's mass could be stored in the Collision Info). The smaller mass should surrender more
// position offset and should slave more to the other's velocity in the static-friction case.
position -= collisionInfo._penetration;
if (glm::length(relativeVelocity) < HALTING_PARTICLE_SPEED) {
// static friction kicks in and particle moves with colliding object
velocity = collisionInfo._addedVelocity;
} else {
glm::vec3 direction = glm::normalize(collisionInfo._penetration);
velocity += glm::dot(relativeVelocity, direction) * (1.0f + collisionInfo._elasticity) * direction; // dynamic reflection
velocity += glm::clamp(collisionInfo._damping, 0.0f, 1.0f) * (relativeVelocity - glm::dot(relativeVelocity, direction) * direction); // dynamic friction
}
}
// change the local particle too...
setPosition(position);
setVelocity(velocity);
}
// MIN_VALID_SPEED is obtained by computing speed gained at one gravity during the shortest expected frame period
// This is a HACK for particles that bounce in a 1.0 gravitational field and should eventually be made more universal.
const float MIN_EXPECTED_FRAME_PERIOD = 0.005f; // 1/200th of a second
const float MIN_VALID_SPEED = 9.8 * MIN_EXPECTED_FRAME_PERIOD / (float)(TREE_SCALE);

View file

@ -16,6 +16,7 @@
#include <QtScript/QScriptEngine>
#include <QtCore/QObject>
#include <CollisionInfo.h>
#include <SharedUtil.h>
#include <OctreePacketData.h>
@ -240,6 +241,8 @@ public:
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);
void applyHardCollision(const CollisionInfo& collisionInfo);
void update(const uint64_t& now);
void collisionWithParticle(Particle* other);
void collisionWithVoxel(VoxelDetail* voxel);

View file

@ -73,6 +73,8 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
const float DAMPING = 0.05f;
const float COLLISION_FREQUENCY = 0.5f;
CollisionInfo collisionInfo;
collisionInfo._damping = DAMPING;
collisionInfo._elasticity = ELASTICITY;
VoxelDetail* voxelDetails = NULL;
if (_voxels->findSpherePenetration(center, radius, collisionInfo._penetration, (void**)&voxelDetails)) {
@ -81,7 +83,8 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
collisionInfo._penetration /= (float)(TREE_SCALE);
applyHardCollision(particle, ELASTICITY, DAMPING, collisionInfo);
particle->applyHardCollision(collisionInfo);
queueParticlePropertiesUpdate(particle);
delete voxelDetails; // cleanup returned details
}
@ -161,6 +164,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
if (_selfAvatar) {
AvatarData* avatar = (AvatarData*)_selfAvatar;
CollisionInfo collisionInfo;
collisionInfo._damping = DAMPING;
collisionInfo._elasticity = ELASTICITY;
if (avatar->findSphereCollision(center, radius, collisionInfo)) {
collisionInfo._addedVelocity /= (float)(TREE_SCALE);
glm::vec3 relativeVelocity = collisionInfo._addedVelocity - particle->getVelocity();
@ -185,7 +190,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
collisionInfo._penetration /= (float)(TREE_SCALE);
applyHardCollision(particle, elasticity, damping, collisionInfo);
particle->applyHardCollision(collisionInfo);
queueParticlePropertiesUpdate(particle);
}
}
}
@ -224,51 +230,14 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
// }
}
// TODO: convert applyHardCollision() to take a CollisionInfo& instead of penetration + addedVelocity
void ParticleCollisionSystem::applyHardCollision(Particle* particle, float elasticity, float damping, const CollisionInfo& collisionInfo) {
//
// Update the particle in response to a hard collision. Position will be reset exactly
// to outside the colliding surface. Velocity will be modified according to elasticity.
//
// if elasticity = 0.0, collision is inelastic (vel normal to collision is lost)
// if elasticity = 1.0, collision is 100% elastic.
//
glm::vec3 position = particle->getPosition();
glm::vec3 velocity = particle->getVelocity();
const float EPSILON = 0.0f;
glm::vec3 relativeVelocity = collisionInfo._addedVelocity - velocity;
float velocityDotPenetration = glm::dot(relativeVelocity, collisionInfo._penetration);
if (velocityDotPenetration < EPSILON) {
// particle is moving into collision surface
position -= collisionInfo._penetration;
if (glm::length(relativeVelocity) < HALTING_SPEED) {
// static friction kicks in and particle moves with colliding object
velocity = collisionInfo._addedVelocity;
} else {
glm::vec3 direction = glm::normalize(collisionInfo._penetration);
velocity += glm::dot(relativeVelocity, direction) * (1.0f + elasticity) * direction; // dynamic reflection
velocity += glm::clamp(damping, 0.0f, 1.0f) * (relativeVelocity - glm::dot(relativeVelocity, direction) * direction); // dynamic friction
}
}
const bool wantDebug = false;
if (wantDebug) {
printf("ParticleCollisionSystem::applyHardCollision() particle id:%d new velocity:%f,%f,%f inHand:%s\n",
particle->getID(), velocity.x, velocity.y, velocity.z, debug::valueOf(particle->getInHand()));
}
// send off the result to the particle server
void ParticleCollisionSystem::queueParticlePropertiesUpdate(Particle* particle) {
// queue the result for sending to the particle server
ParticleProperties properties;
ParticleID particleID(particle->getID());
properties.copyFromParticle(*particle);
properties.setPosition(position * (float)TREE_SCALE);
properties.setVelocity(velocity * (float)TREE_SCALE);
properties.setPosition(particle->getPosition() * (float)TREE_SCALE);
properties.setVelocity(particle->getVelocity() * (float)TREE_SCALE);
_packetSender->queueParticleEditMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, particleID, properties);
// change the local particle too...
particle->setPosition(position);
particle->setVelocity(velocity);
}

View file

@ -47,7 +47,7 @@ public:
void updateCollisionWithVoxels(Particle* particle);
void updateCollisionWithParticles(Particle* particle);
void updateCollisionWithAvatars(Particle* particle);
void applyHardCollision(Particle* particle, float elasticity, float damping, const CollisionInfo& collisionInfo);
void queueParticlePropertiesUpdate(Particle* particle);
void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency);
private:

View file

@ -13,11 +13,19 @@
class CollisionInfo {
public:
CollisionInfo() : _penetration(0.f), _addedVelocity(0.f) { }
CollisionInfo()
: _damping(0.f),
_elasticity(1.f),
_penetration(0.f),
_addedVelocity(0.f) {
}
~CollisionInfo() {}
//glm::vec3 _point;
//glm::vec3 _normal;
float _damping;
float _elasticity;
glm::vec3 _penetration; // depth that bodyA is penetrates bodyB
glm::vec3 _addedVelocity;
};