Adding ModelCollisionInfo struct to get more info about collisions against avatars.

Had to disable some collisions.  Will go back and make them work again soon.
This commit is contained in:
Andrew Meadows 2014-02-07 10:48:30 -08:00
parent 0a4eec448e
commit 7a8186f1da
7 changed files with 85 additions and 38 deletions

View file

@ -271,26 +271,26 @@ bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
return false;
}
bool Avatar::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
glm::vec3& penetration, int skeletonSkipIndex) const {
bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius,
ModelCollisionList& collisions, int skeletonSkipIndex) {
bool didPenetrate = false;
glm::vec3 totalPenetration;
glm::vec3 skeletonPenetration;
if (_skeletonModel.findSpherePenetration(penetratorCenter, penetratorRadius,
skeletonPenetration, 1.0f, skeletonSkipIndex)) {
totalPenetration = addPenetrations(totalPenetration, skeletonPenetration);
ModelCollisionInfo collisionInfo;
int jointIndex = _skeletonModel.findSphereCollision(penetratorCenter, penetratorRadius,
collisionInfo, 1.0f, skeletonSkipIndex);
if (jointIndex != -1) {
collisionInfo._model = &_skeletonModel;
collisions.push_back(collisionInfo);
didPenetrate = true;
}
glm::vec3 facePenetration;
if (_head.getFaceModel().findSpherePenetration(penetratorCenter, penetratorRadius, facePenetration)) {
totalPenetration = addPenetrations(totalPenetration, facePenetration);
jointIndex = _head.getFaceModel().findSphereCollision(penetratorCenter, penetratorRadius, collisionInfo);
if (jointIndex != -1) {
collisionInfo._model = &(_head.getFaceModel());
collisions.push_back(collisionInfo);
didPenetrate = true;
}
if (didPenetrate) {
penetration = totalPenetration;
return true;
}
return false;
return didPenetrate;
}
bool Avatar::findSphereCollisionWithHands(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) {
@ -335,14 +335,17 @@ bool Avatar::findSphereCollisionWithHands(const glm::vec3& sphereCenter, float s
return false;
}
/* adebug TODO: make this work again
bool Avatar::findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) {
if (_skeletonModel.findSpherePenetration(sphereCenter, sphereRadius, collision._penetration)) {
int jointIndex = _skeletonModel.findSphereCollision(sphereCenter, sphereRadius, collision._penetration);
if (jointIndex != -1) {
collision._penetration /= (float)(TREE_SCALE);
collision._addedVelocity = getVelocity();
return true;
}
return false;
}
*/
int Avatar::parseData(const QByteArray& packet) {
// change in position implies movement
@ -404,6 +407,22 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2,
glEnd();
}
void Avatar::updateCollisionFlags() {
_collisionFlags = 0;
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithEnvironment)) {
_collisionFlags |= COLLISION_GROUP_ENVIRONMENT;
}
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) {
_collisionFlags |= COLLISION_GROUP_AVATARS;
}
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) {
_collisionFlags |= COLLISION_GROUP_VOXELS;
}
//if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithParticles)) {
// _collisionFlags |= COLLISION_GROUP_PARTICLES;
//}
}
void Avatar::setScale(float scale) {
_scale = scale;

View file

@ -57,6 +57,8 @@ enum ScreenTintLayer {
NUM_SCREEN_TINT_LAYERS
};
typedef QVector<ModelCollisionInfo> ModelCollisionList;
// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found)
// this is basically in the center of the ground plane. Slightly adjusted. This was asked for by
// Grayson as he's building a street around here for demo dinner 2
@ -96,11 +98,11 @@ public:
/// Checks for penetration between the described sphere and the avatar.
/// \param penetratorCenter the center of the penetration test sphere
/// \param penetratorRadius the radius of the penetration test sphere
/// \param penetration[out] the vector in which to store the penetration
/// \param collisions[out] a list of collisions
/// \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 findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
glm::vec3& penetration, int skeletonSkipIndex = -1) const;
bool findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius,
ModelCollisionList& collisions, int skeletonSkipIndex = -1);
/// Checks for collision between the a sphere and the avatar's (paddle) hands.
/// \param collisionCenter the center of the penetration test sphere
@ -114,7 +116,7 @@ public:
/// \param collisionRadius the radius of the penetration test sphere
/// \param collision[out] the details of the collision point
/// \return whether or not the sphere collided
bool findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision);
//bool findSphereCollisionWithSkeleton(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision);
virtual bool isMyAvatar() { return false; }
@ -124,6 +126,9 @@ public:
float getHeight() const;
public slots:
void updateCollisionFlags();
protected:
Head _head;
Hand _hand;

View file

@ -84,8 +84,7 @@ void Hand::simulate(float deltaTime, bool isMine) {
if (isMine) {
_buckyBalls.simulate(deltaTime);
// TODO: recover this stuff after avatar-avatar collisions work again - Andrew
//updateCollisions();
updateCollisions();
}
calculateGeometry();
@ -172,6 +171,7 @@ void Hand::updateCollisions() {
int leftPalmIndex, rightPalmIndex;
getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
ModelCollisionList collisions;
// check for collisions
for (size_t i = 0; i < getNumPalms(); i++) {
PalmData& palm = getPalms()[i];
@ -224,9 +224,10 @@ void Hand::updateCollisions() {
}
}
}
glm::vec3 avatarPenetration;
if (avatar->findSpherePenetration(palm.getPosition(), scaledPalmRadius, avatarPenetration)) {
totalPenetration = addPenetrations(totalPenetration, avatarPenetration);
if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions)) {
for (size_t j = 0; j < collisions.size(); ++j) {
totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration);
}
// Check for collisions with the other avatar's leap palms
}
}
@ -234,18 +235,23 @@ void Hand::updateCollisions() {
if (Menu::getInstance()->isOptionChecked(MenuOption::HandsCollideWithSelf)) {
// and the current avatar (ignoring everything below the parent of the parent of the last free joint)
glm::vec3 owningPenetration;
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->findSpherePenetration(palm.getPosition(), scaledPalmRadius, owningPenetration, skipIndex)) {
totalPenetration = addPenetrations(totalPenetration, owningPenetration);
if (_owningAvatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, collisions, skipIndex)) {
for (size_t j = 0; j < collisions.size(); ++j) {
totalPenetration = addPenetrations(totalPenetration, collisions[j]._penetration);
}
}
}
// un-penetrate
palm.addToPosition(-totalPenetration);
// we recycle the collisions container, so we clear it for the next loop
collisions.clear();
}
}

View file

@ -225,7 +225,8 @@ void MyAvatar::simulate(float deltaTime) {
updateCollisionWithVoxels(deltaTime, radius);
}
if (_collisionFlags & COLLISION_GROUP_AVATARS) {
updateCollisionWithAvatars(deltaTime);
// TODO: Andrew to implement this
//updateCollisionWithAvatars(deltaTime);
}
}
@ -1017,8 +1018,9 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
glm::vec3 pos = palmProxies[i]._position;
// query against avatar
if (avatar->findSphereCollisionWithSkeleton(pos, palmProxies[i]._radius, collisionInfo)) {
// TODO: Andrew to make this work
// push hand out of penetration
palms[palmProxies[i]._palmIndex].addToPosition(0.5f * collisionInfo._penetration);
//palms[palmProxies[i]._palmIndex].addToPosition(0.5f * collisionInfo._penetration * float(TREE_SCALE));
// print results
//distance = glm::length(collisionInfo._penetration);
//printf("collision i = %d p = [%e, %e, %e] d = %e\n", i, pos.x, pos.y, pos.z, distance);

View file

@ -437,11 +437,11 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
return false;
}
bool Model::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
glm::vec3& penetration, float boneScale, int skipIndex) const {
bool Model::findSphereCollision(const glm::vec3& penetratorCenter, float penetratorRadius,
ModelCollisionInfo& collisionInfo, float boneScale, int skipIndex) const {
int jointIndex = -1;
const glm::vec3 relativeCenter = penetratorCenter - _translation;
const FBXGeometry& geometry = _geometry->getFBXGeometry();
bool didPenetrate = false;
glm::vec3 totalPenetration;
float radiusScale = extractUniformScale(_scale) * boneScale;
for (int i = 0; i < _jointStates.size(); i++) {
@ -468,12 +468,16 @@ bool Model::findSpherePenetration(const glm::vec3& penetratorCenter, float penet
if (findSphereCapsuleConePenetration(relativeCenter, penetratorRadius, start, end,
startRadius, endRadius, bonePenetration)) {
totalPenetration = addPenetrations(totalPenetration, bonePenetration);
didPenetrate = true;
// TODO: Andrew to try to keep the joint furthest toward the root
jointIndex = i;
}
outerContinue: ;
}
if (didPenetrate) {
penetration = totalPenetration;
if (jointIndex != -1) {
// TODO? Andrew to store contactPoint
// don't store collisionInfo._model at this stage, let the outer context do that
collisionInfo._penetration = totalPenetration;
collisionInfo._jointIndex = jointIndex;
return true;
}
return false;

View file

@ -17,6 +17,16 @@
#include "ProgramObject.h"
#include "TextureCache.h"
class Model;
// TODO: Andrew to move this into its own file
class ModelCollisionInfo : public CollisionInfo {
public:
ModelCollisionInfo() : CollisionInfo(), _model(NULL), _jointIndex(-1) {}
Model* _model;
int _jointIndex;
};
/// A generic 3D model displaying geometry loaded from a URL.
class Model : public QObject {
Q_OBJECT
@ -149,8 +159,8 @@ public:
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
glm::vec3& penetration, float boneScale = 1.0f, int skipIndex = -1) const;
bool findSphereCollision(const glm::vec3& penetratorCenter, float penetratorRadius,
ModelCollisionInfo& collision, float boneScale = 1.0f, int skipIndex = -1) const;
void renderCollisionProxies(float alpha);

View file

@ -186,8 +186,9 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
CollisionInfo collisionInfo;
collisionInfo._damping = DAMPING;
collisionInfo._elasticity = ELASTICITY;
if (avatar->findSphereCollisionWithHands(center, radius, collisionInfo) ||
avatar->findSphereCollisionWithSkeleton(center, radius, collisionInfo)) {
if (avatar->findSphereCollisionWithHands(center, radius, collisionInfo)) {
// TODO: Andrew to resurrect particles-vs-avatar body collisions
//avatar->findSphereCollisionWithSkeleton(center, radius, collisionInfo)) {
collisionInfo._addedVelocity /= (float)(TREE_SCALE);
glm::vec3 relativeVelocity = collisionInfo._addedVelocity - particle->getVelocity();
if (glm::dot(relativeVelocity, collisionInfo._penetration) < 0.f) {