cleanup of avatar collisions, prep for more ragdoll collisions

removal of paddle hands
particles use general sphere collision path against avatars
temp removal of skeleton self collision
This commit is contained in:
Andrew Meadows 2014-06-06 10:51:22 -07:00
parent 7f25c3e011
commit ca77eb9d1e
7 changed files with 10 additions and 102 deletions

View file

@ -579,8 +579,8 @@ bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
return false;
}
bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius,
CollisionList& collisions, int skeletonSkipIndex) {
bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius, CollisionList& collisions) {
int skeletonSkipIndex = -1;
return _skeletonModel.findSphereCollisions(penetratorCenter, penetratorRadius, collisions, skeletonSkipIndex);
// Temporarily disabling collisions against the head because most of its collision proxies are bad.
//return getHead()->getFaceModel().findSphereCollisions(penetratorCenter, penetratorRadius, collisions);
@ -613,69 +613,6 @@ bool Avatar::findCollisions(const QVector<const Shape*>& shapes, CollisionList&
return collided;
}
bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) {
if (_collisionGroups & COLLISION_GROUP_PARTICLES) {
return false;
}
bool collided = false;
// first do the hand collisions
const HandData* handData = getHandData();
if (handData) {
for (int i = 0; i < NUM_HANDS; i++) {
const PalmData* palm = handData->getPalm(i);
if (palm && palm->hasPaddle()) {
// create a disk collision proxy where the hand is
int jointIndex = -1;
glm::vec3 handPosition;
if (i == 0) {
_skeletonModel.getLeftHandPosition(handPosition);
jointIndex = _skeletonModel.getLeftHandJointIndex();
}
else {
_skeletonModel.getRightHandPosition(handPosition);
jointIndex = _skeletonModel.getRightHandJointIndex();
}
glm::vec3 fingerAxis = palm->getFingerDirection();
glm::vec3 diskCenter = handPosition + HAND_PADDLE_OFFSET * fingerAxis;
glm::vec3 diskNormal = palm->getNormal();
const float DISK_THICKNESS = 0.08f;
// collide against the disk
glm::vec3 penetration;
if (findSphereDiskPenetration(particleCenter, particleRadius,
diskCenter, HAND_PADDLE_RADIUS, DISK_THICKNESS, diskNormal,
penetration)) {
CollisionInfo* collision = collisions.getNewCollision();
if (collision) {
collision->_type = COLLISION_TYPE_PADDLE_HAND;
collision->_intData = jointIndex;
collision->_penetration = penetration;
collision->_addedVelocity = palm->getVelocity();
collided = true;
} else {
// collisions are full, so we might as well bail now
return collided;
}
}
}
}
}
// then collide against the models
int preNumCollisions = collisions.size();
if (_skeletonModel.findSphereCollisions(particleCenter, particleRadius, collisions)) {
// the Model doesn't have velocity info, so we have to set it for each new collision
int postNumCollisions = collisions.size();
for (int i = preNumCollisions; i < postNumCollisions; ++i) {
CollisionInfo* collision = collisions.getCollision(i);
collision->_penetration /= (float)(TREE_SCALE);
collision->_addedVelocity = getVelocity();
}
collided = true;
}
return collided;
}
glm::quat Avatar::getJointRotation(int index) const {
if (QThread::currentThread() != thread()) {
return AvatarData::getJointRotation(index);

View file

@ -101,14 +101,12 @@ public:
/// \return true if at least one shape collided with avatar
bool findCollisions(const QVector<const Shape*>& shapes, CollisionList& collisions);
/// Checks for penetration between the described sphere and the avatar.
/// Checks for penetration between the a sphere and the avatar's models.
/// \param penetratorCenter the center of the penetration test sphere
/// \param penetratorRadius the radius of the penetration test sphere
/// \param collisions[out] a list to which collisions get appended
/// \param skeletonSkipIndex if not -1, the index of a joint to skip (along with its descendents) in the skeleton model
/// \return whether or not the sphere penetrated
bool findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius,
CollisionList& collisions, int skeletonSkipIndex = -1);
bool findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius, CollisionList& collisions);
/// Checks for penetration between the described plane and the avatar.
/// \param plane the penetration plane
@ -116,13 +114,6 @@ public:
/// \return whether or not the plane penetrated
bool findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions);
/// Checks for collision between the a spherical particle and the avatar (including paddle hands)
/// \param collisionCenter the center of particle's bounding sphere
/// \param collisionRadius the radius of particle's bounding sphere
/// \param collisions[out] a list to which collisions get appended
/// \return whether or not the particle collided
bool findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions);
virtual bool isMyAvatar() { return false; }
virtual glm::quat getJointRotation(int index) const;

View file

@ -95,6 +95,7 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
}
void Hand::collideAgainstOurself() {
/* TODO: Andrew to re-implement this
if (!Menu::getInstance()->isOptionChecked(MenuOption::HandsCollideWithSelf)) {
return;
}
@ -125,6 +126,7 @@ void Hand::collideAgainstOurself() {
palm.addToPenetration(totalPenetration);
}
}
*/
}
void Hand::resolvePenetrations() {

View file

@ -223,7 +223,7 @@ public:
virtual const glm::vec3& getVelocity() const { return vec3Zero; }
virtual bool findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) {
virtual bool findSphereCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) {
return false;
}

View file

@ -202,14 +202,13 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
foreach (const AvatarSharedPointer& avatarPointer, _avatars->getAvatarHash()) {
AvatarData* avatar = avatarPointer.data();
// use a very generous bounding radius since the arms can stretch
float totalRadius = 2.f * avatar->getBoundingRadius() + radius;
float totalRadius = avatar->getBoundingRadius() + radius;
glm::vec3 relativePosition = center - avatar->getPosition();
if (glm::dot(relativePosition, relativePosition) > (totalRadius * totalRadius)) {
continue;
}
if (avatar->findParticleCollisions(center, radius, _collisions)) {
if (avatar->findSphereCollisions(center, radius, _collisions)) {
int numCollisions = _collisions.size();
for (int i = 0; i < numCollisions; ++i) {
CollisionInfo* collision = _collisions.getCollision(i);
@ -222,25 +221,6 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
if (glm::dot(relativeVelocity, collision->_penetration) <= 0.f) {
// only collide when particle and collision point are moving toward each other
// (doing this prevents some "collision snagging" when particle penetrates the object)
// HACK BEGIN: to allow paddle hands to "hold" particles we attenuate soft collisions against them.
if (collision->_type == COLLISION_TYPE_PADDLE_HAND) {
// NOTE: the physics are wrong (particles cannot roll) but it IS possible to catch a slow moving particle.
// TODO: make this less hacky when we have more per-collision details
float elasticity = ELASTICITY;
float attenuationFactor = glm::length(collision->_addedVelocity) / HALTING_SPEED;
float damping = DAMPING;
if (attenuationFactor < 1.f) {
collision->_addedVelocity *= attenuationFactor;
elasticity *= attenuationFactor;
// NOTE: the math below keeps the damping piecewise continuous,
// while ramping it up to 1 when attenuationFactor = 0
damping = DAMPING + (1.f - attenuationFactor) * (1.f - DAMPING);
}
collision->_damping = damping;
}
// HACK END
updateCollisionSound(particle, collision->_penetration, COLLISION_FREQUENCY);
collision->_penetration /= (float)(TREE_SCALE);
particle->applyHardCollision(*collision);

View file

@ -38,8 +38,7 @@ CollisionInfo* CollisionList::getLastCollision() {
}
void CollisionList::clear() {
// we rely on the external context to properly set or clear the data members of a collision
// whenever it is used.
// we rely on the external context to properly set or clear the data members of CollisionInfos
/*
for (int i = 0; i < _size; ++i) {
// we only clear the important stuff

View file

@ -19,7 +19,6 @@
enum CollisionType {
COLLISION_TYPE_UNKNOWN = 0,
COLLISION_TYPE_PADDLE_HAND,
COLLISION_TYPE_MODEL,
// _data = pointer to Model that owns joint
// _intData = joint index