Moving hand-avatar collision trigger calls into MyAvatar

Also renaming some methods in Model to be more descriptive.
This commit is contained in:
Andrew Meadows 2014-02-12 08:29:22 -08:00
parent 6c4ecb0246
commit 04bc05cfe6
7 changed files with 71 additions and 75 deletions

View file

@ -445,20 +445,19 @@ float Avatar::getHeight() const {
return extents.maximum.y - extents.minimum.y;
}
bool Avatar::isPokeable(ModelCollisionInfo& collision) const {
bool Avatar::collisionWouldMoveAvatar(ModelCollisionInfo& collision) const {
// ATM only the Skeleton is pokeable
// TODO: make poke affect head
if (collision._model == &_skeletonModel && collision._jointIndex != -1) {
return _skeletonModel.isPokeable(collision);
return _skeletonModel.collisionHitsMoveableJoint(collision);
}
return false;
}
bool Avatar::poke(ModelCollisionInfo& collision) {
void Avatar::applyCollision(ModelCollisionInfo& collision) {
if (collision._model == &_skeletonModel && collision._jointIndex != -1) {
return _skeletonModel.poke(collision);
_skeletonModel.applyCollision(collision);
}
return false;
}
float Avatar::getPelvisFloatingHeight() const {

View file

@ -129,11 +129,10 @@ public:
float getHeight() const;
/// \return true if we expect the avatar would move as a result of the collision
bool isPokeable(ModelCollisionInfo& collision) const;
bool collisionWouldMoveAvatar(ModelCollisionInfo& collision) const;
/// \param collision a data structure for storing info about collisions against Models
/// \return true if the collision affects the Avatar models
bool poke(ModelCollisionInfo& collision);
void applyCollision(ModelCollisionInfo& collision);
public slots:
void updateCollisionFlags();

View file

@ -84,7 +84,6 @@ void Hand::simulate(float deltaTime, bool isMine) {
if (isMine) {
_buckyBalls.simulate(deltaTime);
updateCollisions();
}
calculateGeometry();
@ -166,16 +165,11 @@ void Hand::simulate(float deltaTime, bool isMine) {
}
}
void Hand::updateCollisions() {
collideAgainstOtherAvatars();
collideAgainstOurself();
}
void Hand::collideAgainstOtherAvatars() {
if (!Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) {
void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
if (!avatar || avatar == _owningAvatar) {
// don't collide with our own hands (that is done elsewhere)
return;
}
ModelCollisionList collisions;
float scaledPalmRadius = PALM_COLLISION_RADIUS * _owningAvatar->getScale();
for (size_t i = 0; i < getNumPalms(); i++) {
PalmData& palm = getPalms()[i];
@ -183,58 +177,61 @@ void Hand::collideAgainstOtherAvatars() {
continue;
}
glm::vec3 totalPenetration;
// check other avatars
foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) {
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
if (avatar == _owningAvatar) {
// don't collid with our own hands
continue;
}
collisions.clear();
if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
// Check for palm collisions
glm::vec3 myPalmPosition = palm.getPosition();
float palmCollisionDistance = 0.1f;
bool wasColliding = palm.getIsCollidingWithPalm();
palm.setIsCollidingWithPalm(false);
// If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound
for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) {
PalmData& otherPalm = avatar->getHand().getPalms()[j];
if (!otherPalm.isActive()) {
continue;
}
glm::vec3 otherPalmPosition = otherPalm.getPosition();
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
palm.setIsCollidingWithPalm(true);
if (!wasColliding) {
const float PALM_COLLIDE_VOLUME = 1.f;
const float PALM_COLLIDE_FREQUENCY = 1000.f;
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
PALM_COLLIDE_FREQUENCY,
PALM_COLLIDE_DURATION_MAX,
PALM_COLLIDE_DECAY_PER_SAMPLE);
// 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;
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
// add slapback here
}
ModelCollisionList collisions;
if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
// Check for palm collisions
glm::vec3 myPalmPosition = palm.getPosition();
float palmCollisionDistance = 0.1f;
bool wasColliding = palm.getIsCollidingWithPalm();
palm.setIsCollidingWithPalm(false);
// If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound
for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) {
PalmData& otherPalm = avatar->getHand().getPalms()[j];
if (!otherPalm.isActive()) {
continue;
}
glm::vec3 otherPalmPosition = otherPalm.getPosition();
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
palm.setIsCollidingWithPalm(true);
if (!wasColliding) {
const float PALM_COLLIDE_VOLUME = 1.f;
const float PALM_COLLIDE_FREQUENCY = 1000.f;
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
PALM_COLLIDE_FREQUENCY,
PALM_COLLIDE_DURATION_MAX,
PALM_COLLIDE_DECAY_PER_SAMPLE);
// 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;
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
// add slapback here
}
}
}
}
if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) {
for (int j = 0; j < collisions.size(); ++j) {
// we don't resolve penetrations that would poke the other avatar
if (!avatar->isPokeable(collisions[j])) {
}
if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) {
for (int j = 0; j < collisions.size(); ++j) {
if (isMyHand) {
if (!avatar->collisionWouldMoveAvatar(collisions[j])) {
// we resolve the hand from collision when it belongs to MyAvatar AND the other Avatar is
// not expected to respond to the collision (hand hit unmovable part of their Avatar)
totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration);
}
} else {
// when this !isMyHand then avatar is MyAvatar and we apply the collision
// which might not do anything (hand hit unmovable part of MyAvatar) however
// we don't resolve the hand's penetration (we expect their simulation
// to do the right thing).
avatar->applyCollision(collisions[j]);
}
}
}
// resolve penetration
palm.addToPosition(-totalPenetration);
if (isMyHand) {
// resolve penetration
palm.addToPosition(-totalPenetration);
}
}
}

View file

@ -67,6 +67,9 @@ public:
glm::vec3 getAndResetGrabDeltaVelocity();
glm::quat getAndResetGrabRotation();
void collideAgainstAvatar(Avatar* avatar, bool isMyHand);
void collideAgainstOurself();
private:
// disallow copies of the Hand, copy of owning Avatar is disallowed too
Hand(const Hand&);
@ -96,10 +99,6 @@ private:
void renderLeapHands(bool isMine);
void renderLeapFingerTrails();
void updateCollisions();
void collideAgainstOtherAvatars();
void collideAgainstOurself();
void calculateGeometry();
void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime);

View file

@ -344,6 +344,7 @@ void MyAvatar::simulate(float deltaTime) {
_position += _velocity * deltaTime;
// update avatar skeleton and simulate hand and head
_hand.collideAgainstOurself();
_hand.simulate(deltaTime, true);
_skeletonModel.simulate(deltaTime);
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
@ -1050,11 +1051,13 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
avatar->getPosition(), theirCapsuleRadius, theirCapsuleHeight, penetration)) {
// move the avatar out by half the penetration
setPosition(_position - 0.5f * penetration);
glm::vec3 pushOut = 0.5f * penetration;
}
// collide their hands against our movable limbs
// collide our hands against them
_hand.collideAgainstAvatar(avatar, true);
// collide their hands against us
avatar->getHand().collideAgainstAvatar(this, false);
}
}
}

View file

@ -722,7 +722,7 @@ void Model::renderCollisionProxies(float alpha) {
glPopMatrix();
}
bool Model::isPokeable(ModelCollisionInfo& collision) const {
bool Model::collisionHitsMoveableJoint(ModelCollisionInfo& collision) const {
// the joint is pokable by a collision if it exists and is free to move
const FBXJoint& joint = _geometry->getFBXGeometry().joints[collision._jointIndex];
if (joint.parentIndex == -1 ||
@ -736,7 +736,7 @@ bool Model::isPokeable(ModelCollisionInfo& collision) const {
return !freeLineage.isEmpty();
}
bool Model::poke(ModelCollisionInfo& collision) {
void Model::applyCollision(ModelCollisionInfo& collision) {
// This needs work. At the moment it can wiggle joints that are free to move (such as arms)
// but unmovable joints (such as torso) cannot be influenced at all.
glm::vec3 jointPosition(0.f);
@ -760,11 +760,10 @@ bool Model::poke(ModelCollisionInfo& collision) {
getJointPosition(jointIndex, end);
glm::vec3 newEnd = start + glm::angleAxis(glm::degrees(angle), axis) * (end - start);
// try to move it
return setJointPosition(jointIndex, newEnd, -1, true);
setJointPosition(jointIndex, newEnd, -1, true);
}
}
}
return false;
}
void Model::deleteGeometry() {

View file

@ -167,12 +167,12 @@ public:
void renderCollisionProxies(float alpha);
/// \return true if the collision would move the model
bool isPokeable(ModelCollisionInfo& collision) const;
/// \return true if the collision is against a moveable joint
bool collisionHitsMoveableJoint(ModelCollisionInfo& collision) const;
/// \param collisionInfo info about the collision
/// \return true if collision affects the Model
bool poke(ModelCollisionInfo& collisionInfo);
/// Use the collisionInfo to affect the model
void applyCollision(ModelCollisionInfo& collisionInfo);
protected: