mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 22:16:39 +02:00
Moving applyHardCollision to the Particle class. Adding daming and elasticity to CollisionInfo.
This commit is contained in:
parent
5cc2b029cf
commit
2f02ee0b31
5 changed files with 68 additions and 45 deletions
|
@ -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
|
// 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_EXPECTED_FRAME_PERIOD = 0.005f; // 1/200th of a second
|
||||||
const float MIN_VALID_SPEED = 9.8 * MIN_EXPECTED_FRAME_PERIOD / (float)(TREE_SCALE);
|
const float MIN_VALID_SPEED = 9.8 * MIN_EXPECTED_FRAME_PERIOD / (float)(TREE_SCALE);
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
#include <CollisionInfo.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <OctreePacketData.h>
|
#include <OctreePacketData.h>
|
||||||
|
|
||||||
|
@ -240,6 +241,8 @@ public:
|
||||||
|
|
||||||
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);
|
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);
|
||||||
|
|
||||||
|
void applyHardCollision(const CollisionInfo& collisionInfo);
|
||||||
|
|
||||||
void update(const uint64_t& now);
|
void update(const uint64_t& now);
|
||||||
void collisionWithParticle(Particle* other);
|
void collisionWithParticle(Particle* other);
|
||||||
void collisionWithVoxel(VoxelDetail* voxel);
|
void collisionWithVoxel(VoxelDetail* voxel);
|
||||||
|
|
|
@ -73,6 +73,8 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
const float DAMPING = 0.05f;
|
const float DAMPING = 0.05f;
|
||||||
const float COLLISION_FREQUENCY = 0.5f;
|
const float COLLISION_FREQUENCY = 0.5f;
|
||||||
CollisionInfo collisionInfo;
|
CollisionInfo collisionInfo;
|
||||||
|
collisionInfo._damping = DAMPING;
|
||||||
|
collisionInfo._elasticity = ELASTICITY;
|
||||||
VoxelDetail* voxelDetails = NULL;
|
VoxelDetail* voxelDetails = NULL;
|
||||||
if (_voxels->findSpherePenetration(center, radius, collisionInfo._penetration, (void**)&voxelDetails)) {
|
if (_voxels->findSpherePenetration(center, radius, collisionInfo._penetration, (void**)&voxelDetails)) {
|
||||||
|
|
||||||
|
@ -81,7 +83,8 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
|
|
||||||
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
|
||||||
collisionInfo._penetration /= (float)(TREE_SCALE);
|
collisionInfo._penetration /= (float)(TREE_SCALE);
|
||||||
applyHardCollision(particle, ELASTICITY, DAMPING, collisionInfo);
|
particle->applyHardCollision(collisionInfo);
|
||||||
|
queueParticlePropertiesUpdate(particle);
|
||||||
|
|
||||||
delete voxelDetails; // cleanup returned details
|
delete voxelDetails; // cleanup returned details
|
||||||
}
|
}
|
||||||
|
@ -161,6 +164,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
if (_selfAvatar) {
|
if (_selfAvatar) {
|
||||||
AvatarData* avatar = (AvatarData*)_selfAvatar;
|
AvatarData* avatar = (AvatarData*)_selfAvatar;
|
||||||
CollisionInfo collisionInfo;
|
CollisionInfo collisionInfo;
|
||||||
|
collisionInfo._damping = DAMPING;
|
||||||
|
collisionInfo._elasticity = ELASTICITY;
|
||||||
if (avatar->findSphereCollision(center, radius, collisionInfo)) {
|
if (avatar->findSphereCollision(center, radius, collisionInfo)) {
|
||||||
collisionInfo._addedVelocity /= (float)(TREE_SCALE);
|
collisionInfo._addedVelocity /= (float)(TREE_SCALE);
|
||||||
glm::vec3 relativeVelocity = collisionInfo._addedVelocity - particle->getVelocity();
|
glm::vec3 relativeVelocity = collisionInfo._addedVelocity - particle->getVelocity();
|
||||||
|
@ -185,7 +190,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
|
|
||||||
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
|
||||||
collisionInfo._penetration /= (float)(TREE_SCALE);
|
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::queueParticlePropertiesUpdate(Particle* particle) {
|
||||||
void ParticleCollisionSystem::applyHardCollision(Particle* particle, float elasticity, float damping, const CollisionInfo& collisionInfo) {
|
// queue the result for sending to the particle server
|
||||||
//
|
|
||||||
// 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
|
|
||||||
ParticleProperties properties;
|
ParticleProperties properties;
|
||||||
ParticleID particleID(particle->getID());
|
ParticleID particleID(particle->getID());
|
||||||
properties.copyFromParticle(*particle);
|
properties.copyFromParticle(*particle);
|
||||||
properties.setPosition(position * (float)TREE_SCALE);
|
properties.setPosition(particle->getPosition() * (float)TREE_SCALE);
|
||||||
properties.setVelocity(velocity * (float)TREE_SCALE);
|
properties.setVelocity(particle->getVelocity() * (float)TREE_SCALE);
|
||||||
_packetSender->queueParticleEditMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, particleID, properties);
|
_packetSender->queueParticleEditMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, particleID, properties);
|
||||||
|
|
||||||
// change the local particle too...
|
|
||||||
particle->setPosition(position);
|
|
||||||
particle->setVelocity(velocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
void updateCollisionWithVoxels(Particle* particle);
|
void updateCollisionWithVoxels(Particle* particle);
|
||||||
void updateCollisionWithParticles(Particle* particle);
|
void updateCollisionWithParticles(Particle* particle);
|
||||||
void updateCollisionWithAvatars(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);
|
void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -13,11 +13,19 @@
|
||||||
|
|
||||||
class CollisionInfo {
|
class CollisionInfo {
|
||||||
public:
|
public:
|
||||||
CollisionInfo() : _penetration(0.f), _addedVelocity(0.f) { }
|
CollisionInfo()
|
||||||
|
: _damping(0.f),
|
||||||
|
_elasticity(1.f),
|
||||||
|
_penetration(0.f),
|
||||||
|
_addedVelocity(0.f) {
|
||||||
|
}
|
||||||
|
|
||||||
~CollisionInfo() {}
|
~CollisionInfo() {}
|
||||||
|
|
||||||
//glm::vec3 _point;
|
//glm::vec3 _point;
|
||||||
//glm::vec3 _normal;
|
//glm::vec3 _normal;
|
||||||
|
float _damping;
|
||||||
|
float _elasticity;
|
||||||
glm::vec3 _penetration; // depth that bodyA is penetrates bodyB
|
glm::vec3 _penetration; // depth that bodyA is penetrates bodyB
|
||||||
glm::vec3 _addedVelocity;
|
glm::vec3 _addedVelocity;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue