Splitting hand collisions between other avatars and ourself.

This commit is contained in:
Andrew Meadows 2014-02-11 14:38:31 -08:00
parent 3b3359abce
commit 6c4ecb0246
3 changed files with 88 additions and 67 deletions

View file

@ -167,91 +167,106 @@ void Hand::simulate(float deltaTime, bool isMine) {
} }
void Hand::updateCollisions() { void Hand::updateCollisions() {
// use position to obtain the left and right palm indices collideAgainstOtherAvatars();
int leftPalmIndex, rightPalmIndex; collideAgainstOurself();
getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); }
void Hand::collideAgainstOtherAvatars() {
if (!Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) {
return;
}
ModelCollisionList collisions; ModelCollisionList collisions;
// check for collisions float scaledPalmRadius = PALM_COLLISION_RADIUS * _owningAvatar->getScale();
for (size_t i = 0; i < getNumPalms(); i++) { for (size_t i = 0; i < getNumPalms(); i++) {
PalmData& palm = getPalms()[i]; PalmData& palm = getPalms()[i];
if (!palm.isActive()) { if (!palm.isActive()) {
continue; continue;
} }
float scaledPalmRadius = PALM_COLLISION_RADIUS * _owningAvatar->getScale();
glm::vec3 totalPenetration; glm::vec3 totalPenetration;
// check other avatars
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) {
// check other avatars Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { if (avatar == _owningAvatar) {
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data()); // don't collid with our own hands
if (avatar == _owningAvatar) { continue;
// don't collid with our own hands }
continue; collisions.clear();
} if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) { // Check for palm collisions
// Check for palm collisions glm::vec3 myPalmPosition = palm.getPosition();
glm::vec3 myPalmPosition = palm.getPosition(); float palmCollisionDistance = 0.1f;
float palmCollisionDistance = 0.1f; bool wasColliding = palm.getIsCollidingWithPalm();
bool wasColliding = palm.getIsCollidingWithPalm(); palm.setIsCollidingWithPalm(false);
palm.setIsCollidingWithPalm(false); // If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound
// If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) {
for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) { PalmData& otherPalm = avatar->getHand().getPalms()[j];
PalmData& otherPalm = avatar->getHand().getPalms()[j]; if (!otherPalm.isActive()) {
if (!otherPalm.isActive()) { continue;
continue; }
} glm::vec3 otherPalmPosition = otherPalm.getPosition();
glm::vec3 otherPalmPosition = otherPalm.getPosition(); if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) { palm.setIsCollidingWithPalm(true);
palm.setIsCollidingWithPalm(true); if (!wasColliding) {
if (!wasColliding) { const float PALM_COLLIDE_VOLUME = 1.f;
const float PALM_COLLIDE_VOLUME = 1.f; const float PALM_COLLIDE_FREQUENCY = 1000.f;
const float PALM_COLLIDE_FREQUENCY = 1000.f; const float PALM_COLLIDE_DURATION_MAX = 0.75f;
const float PALM_COLLIDE_DURATION_MAX = 0.75f; const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f; Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME, PALM_COLLIDE_FREQUENCY,
PALM_COLLIDE_FREQUENCY, PALM_COLLIDE_DURATION_MAX,
PALM_COLLIDE_DURATION_MAX, PALM_COLLIDE_DECAY_PER_SAMPLE);
PALM_COLLIDE_DECAY_PER_SAMPLE); // If the other person's palm is in motion, move mine downward to show I was hit
// If the other person's palm is in motion, move mine downward to show I was hit const float MIN_VELOCITY_FOR_SLAP = 0.05f;
const float MIN_VELOCITY_FOR_SLAP = 0.05f; if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) { // add slapback here
// add slapback here
}
} }
} }
} }
} }
if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) { }
for (int j = 0; j < collisions.size(); ++j) { if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) {
// we don't resolve penetrations that would poke the other avatar for (int j = 0; j < collisions.size(); ++j) {
if (!avatar->isPokeable(collisions[j])) { // we don't resolve penetrations that would poke the other avatar
totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); if (!avatar->isPokeable(collisions[j])) {
} totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration);
} }
} }
} }
} }
// resolve penetration
if (Menu::getInstance()->isOptionChecked(MenuOption::HandsCollideWithSelf)) { palm.addToPosition(-totalPenetration);
// and the current avatar (ignoring everything below the parent of the parent of the last free joint) }
collisions.clear(); }
const Model& skeletonModel = _owningAvatar->getSkeletonModel();
int skipIndex = skeletonModel.getParentJointIndex(skeletonModel.getParentJointIndex( void Hand::collideAgainstOurself() {
skeletonModel.getLastFreeJointIndex((i == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() : if (!Menu::getInstance()->isOptionChecked(MenuOption::HandsCollideWithSelf)) {
(i == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1))); return;
if (_owningAvatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions, skipIndex)) { }
for (int j = 0; j < collisions.size(); ++j) {
totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration); ModelCollisionList collisions;
} int leftPalmIndex, rightPalmIndex;
getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
float scaledPalmRadius = PALM_COLLISION_RADIUS * _owningAvatar->getScale();
for (size_t i = 0; i < getNumPalms(); i++) {
PalmData& palm = getPalms()[i];
if (!palm.isActive()) {
continue;
}
glm::vec3 totalPenetration;
// and the current avatar (ignoring everything below the parent of the parent of the last free joint)
collisions.clear();
const Model& skeletonModel = _owningAvatar->getSkeletonModel();
int skipIndex = skeletonModel.getParentJointIndex(skeletonModel.getParentJointIndex(
skeletonModel.getLastFreeJointIndex((i == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() :
(i == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1)));
if (_owningAvatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions, skipIndex)) {
for (int j = 0; j < collisions.size(); ++j) {
totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration);
} }
} }
// resolve penetration
// un-penetrate
palm.addToPosition(-totalPenetration); palm.addToPosition(-totalPenetration);
// we recycle the collisions container, so we clear it for the next loop
collisions.clear();
} }
} }

View file

@ -97,6 +97,9 @@ private:
void renderLeapFingerTrails(); void renderLeapFingerTrails();
void updateCollisions(); void updateCollisions();
void collideAgainstOtherAvatars();
void collideAgainstOurself();
void calculateGeometry(); void calculateGeometry();
void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime); void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime);

View file

@ -1052,6 +1052,9 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
setPosition(_position - 0.5f * penetration); setPosition(_position - 0.5f * penetration);
glm::vec3 pushOut = 0.5f * penetration; glm::vec3 pushOut = 0.5f * penetration;
} }
// collide their hands against our movable limbs
} }
} }
} }