overhaul of CollisionInfo

store Cube info for sphereAACube collisions
This commit is contained in:
Andrew Meadows 2014-05-07 11:40:00 -07:00
parent 6c289b682d
commit 9fc1c765d3
6 changed files with 62 additions and 27 deletions

View file

@ -634,8 +634,8 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti
penetration)) { penetration)) {
CollisionInfo* collision = collisions.getNewCollision(); CollisionInfo* collision = collisions.getNewCollision();
if (collision) { if (collision) {
collision->_type = PADDLE_HAND_COLLISION; collision->_type = COLLISION_TYPE_PADDLE_HAND;
collision->_flags = jointIndex; collision->_intData = jointIndex;
collision->_penetration = penetration; collision->_penetration = penetration;
collision->_addedVelocity = palm->getVelocity(); collision->_addedVelocity = palm->getVelocity();
collided = true; collided = true;
@ -844,11 +844,11 @@ float Avatar::getHeadHeight() const {
} }
bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const { bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const {
if (!collision._data || collision._type != MODEL_COLLISION) { if (!collision._data || collision._type != COLLISION_TYPE_MODEL) {
return false; return false;
} }
Model* model = static_cast<Model*>(collision._data); Model* model = static_cast<Model*>(collision._data);
int jointIndex = collision._flags; int jointIndex = collision._intData;
if (model == &(_skeletonModel) && jointIndex != -1) { if (model == &(_skeletonModel) && jointIndex != -1) {
// collision response of skeleton is temporarily disabled // collision response of skeleton is temporarily disabled
@ -856,7 +856,7 @@ bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const {
//return _skeletonModel.collisionHitsMoveableJoint(collision); //return _skeletonModel.collisionHitsMoveableJoint(collision);
} }
if (model == &(getHead()->getFaceModel())) { if (model == &(getHead()->getFaceModel())) {
// ATM we always handle MODEL_COLLISIONS against the face. // ATM we always handle COLLISION_TYPE_MODEL against the face.
return true; return true;
} }
return false; return false;

View file

@ -743,9 +743,9 @@ bool Model::findSphereCollisions(const glm::vec3& sphereCenter, float sphereRadi
} }
if (ShapeCollider::collideShapes(&sphere, _jointShapes[i], collisions)) { if (ShapeCollider::collideShapes(&sphere, _jointShapes[i], collisions)) {
CollisionInfo* collision = collisions.getLastCollision(); CollisionInfo* collision = collisions.getLastCollision();
collision->_type = MODEL_COLLISION; collision->_type = COLLISION_TYPE_MODEL;
collision->_data = (void*)(this); collision->_data = (void*)(this);
collision->_flags = i; collision->_intData = i;
collided = true; collided = true;
} }
outerContinue: ; outerContinue: ;
@ -759,9 +759,9 @@ bool Model::findPlaneCollisions(const glm::vec4& plane, CollisionList& collision
for (int i = 0; i < _jointShapes.size(); i++) { for (int i = 0; i < _jointShapes.size(); i++) {
if (ShapeCollider::collideShapes(&planeShape, _jointShapes[i], collisions)) { if (ShapeCollider::collideShapes(&planeShape, _jointShapes[i], collisions)) {
CollisionInfo* collision = collisions.getLastCollision(); CollisionInfo* collision = collisions.getLastCollision();
collision->_type = MODEL_COLLISION; collision->_type = COLLISION_TYPE_MODEL;
collision->_data = (void*)(this); collision->_data = (void*)(this);
collision->_flags = i; collision->_intData = i;
collided = true; collided = true;
} }
} }
@ -1210,15 +1210,15 @@ void Model::renderBoundingCollisionShapes(float alpha) {
} }
bool Model::collisionHitsMoveableJoint(CollisionInfo& collision) const { bool Model::collisionHitsMoveableJoint(CollisionInfo& collision) const {
if (collision._type == MODEL_COLLISION) { if (collision._type == COLLISION_TYPE_MODEL) {
// the joint is pokable by a collision if it exists and is free to move // the joint is pokable by a collision if it exists and is free to move
const FBXJoint& joint = _geometry->getFBXGeometry().joints[collision._flags]; const FBXJoint& joint = _geometry->getFBXGeometry().joints[collision._intData];
if (joint.parentIndex == -1 || _jointStates.isEmpty()) { if (joint.parentIndex == -1 || _jointStates.isEmpty()) {
return false; return false;
} }
// an empty freeLineage means the joint can't move // an empty freeLineage means the joint can't move
const FBXGeometry& geometry = _geometry->getFBXGeometry(); const FBXGeometry& geometry = _geometry->getFBXGeometry();
int jointIndex = collision._flags; int jointIndex = collision._intData;
const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage; const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
return !freeLineage.isEmpty(); return !freeLineage.isEmpty();
} }
@ -1226,12 +1226,12 @@ bool Model::collisionHitsMoveableJoint(CollisionInfo& collision) const {
} }
void Model::applyCollision(CollisionInfo& collision) { void Model::applyCollision(CollisionInfo& collision) {
if (collision._type != MODEL_COLLISION) { if (collision._type != COLLISION_TYPE_MODEL) {
return; return;
} }
glm::vec3 jointPosition(0.f); glm::vec3 jointPosition(0.f);
int jointIndex = collision._flags; int jointIndex = collision._intData;
if (getJointPosition(jointIndex, jointPosition)) { if (getJointPosition(jointIndex, jointPosition)) {
const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex]; const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex];
if (joint.parentIndex != -1) { if (joint.parentIndex != -1) {

View file

@ -224,7 +224,7 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
// (doing this prevents some "collision snagging" when particle penetrates the object) // (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. // HACK BEGIN: to allow paddle hands to "hold" particles we attenuate soft collisions against them.
if (collision->_type == PADDLE_HAND_COLLISION) { 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. // 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 // TODO: make this less hacky when we have more per-collision details
float elasticity = ELASTICITY; float elasticity = ELASTICITY;

View file

@ -38,19 +38,24 @@ CollisionInfo* CollisionList::getLastCollision() {
} }
void CollisionList::clear() { void CollisionList::clear() {
// we rely on the external context to properly set or clear the data members of a collision
// whenever it is used.
/*
for (int i = 0; i < _size; ++i) { for (int i = 0; i < _size; ++i) {
// we only clear the important stuff // we only clear the important stuff
CollisionInfo& collision = _collisions[i]; CollisionInfo& collision = _collisions[i];
collision._type = BASE_COLLISION; collision._type = COLLISION_TYPE_UNKNOWN;
collision._data = NULL; // CollisionInfo does not own whatever this points to. //collision._data = NULL;
collision._flags = 0; //collision._intData = 0;
// we rely on the consumer to properly overwrite these fields when the collision is "created" //collision._floatDAta = 0.0f;
//collision._vecData = glm::vec3(0.0f);
//collision._damping; //collision._damping;
//collision._elasticity; //collision._elasticity;
//collision._contactPoint; //collision._contactPoint;
//collision._penetration; //collision._penetration;
//collision._addedVelocity; //collision._addedVelocity;
} }
*/
_size = 0; _size = 0;
} }

View file

@ -18,9 +18,14 @@
#include <QVector> #include <QVector>
enum CollisionType { enum CollisionType {
BASE_COLLISION = 0, COLLISION_TYPE_UNKNOWN = 0,
PADDLE_HAND_COLLISION, COLLISION_TYPE_PADDLE_HAND,
MODEL_COLLISION, COLLISION_TYPE_MODEL,
// _data = pointer to Model that owns joint
// _intData = joint index
COLLISION_TYPE_AACUBE,
// _floatData = cube side
// _vecData = cube center
}; };
const quint32 COLLISION_GROUP_ENVIRONMENT = 1U << 0; const quint32 COLLISION_GROUP_ENVIRONMENT = 1U << 0;
@ -39,7 +44,7 @@ public:
CollisionInfo() CollisionInfo()
: _type(0), : _type(0),
_data(NULL), _data(NULL),
_flags(0), _intData(0),
_damping(0.f), _damping(0.f),
_elasticity(1.f), _elasticity(1.f),
_contactPoint(0.f), _contactPoint(0.f),
@ -50,7 +55,7 @@ public:
CollisionInfo(qint32 type) CollisionInfo(qint32 type)
: _type(type), : _type(type),
_data(NULL), _data(NULL),
_flags(0), _intData(0),
_damping(0.f), _damping(0.f),
_elasticity(1.f), _elasticity(1.f),
_contactPoint(0.f), _contactPoint(0.f),
@ -60,9 +65,13 @@ public:
~CollisionInfo() {} ~CollisionInfo() {}
qint32 _type; // type of Collision (will determine what is supposed to be in _data and _flags) int _type; // type of Collision
void* _data; // pointer to user supplied data
quint32 _flags; // 32 bits for whatever // the value of the *Data fields depend on the type
void* _data;
int _intData;
float _floatData;
glm::vec3 _vecData;
float _damping; // range [0,1] of friction coeficient float _damping; // range [0,1] of friction coeficient
float _elasticity; // range [0,1] of energy conservation float _elasticity; // range [0,1] of energy conservation

View file

@ -132,6 +132,7 @@ bool sphereSphere(const SphereShape* sphereA, const SphereShape* sphereB, Collis
// penetration points from A into B // penetration points from A into B
CollisionInfo* collision = collisions.getNewCollision(); CollisionInfo* collision = collisions.getNewCollision();
if (collision) { if (collision) {
collision->_type = COLLISION_TYPE_UNKNOWN;
collision->_penetration = BA * (totalRadius - distance); collision->_penetration = BA * (totalRadius - distance);
// contactPoint is on surface of A // contactPoint is on surface of A
collision->_contactPoint = sphereA->getPosition() + sphereA->getRadius() * BA; collision->_contactPoint = sphereA->getPosition() + sphereA->getRadius() * BA;
@ -179,6 +180,7 @@ bool sphereCapsule(const SphereShape* sphereA, const CapsuleShape* capsuleB, Col
collision->_penetration = (totalRadius - radialDistance) * radialAxis; // points from A into B collision->_penetration = (totalRadius - radialDistance) * radialAxis; // points from A into B
// contactPoint is on surface of sphereA // contactPoint is on surface of sphereA
collision->_contactPoint = sphereA->getPosition() + sphereA->getRadius() * radialAxis; collision->_contactPoint = sphereA->getPosition() + sphereA->getRadius() * radialAxis;
collision->_type = COLLISION_TYPE_UNKNOWN;
} else { } else {
// A is on B's axis, so the penetration is undefined... // A is on B's axis, so the penetration is undefined...
if (absAxialDistance > capsuleB->getHalfHeight()) { if (absAxialDistance > capsuleB->getHalfHeight()) {
@ -200,6 +202,7 @@ bool sphereCapsule(const SphereShape* sphereA, const CapsuleShape* capsuleB, Col
collision->_penetration = (sign * (totalRadius + capsuleB->getHalfHeight() - absAxialDistance)) * capsuleAxis; collision->_penetration = (sign * (totalRadius + capsuleB->getHalfHeight() - absAxialDistance)) * capsuleAxis;
// contactPoint is on surface of sphereA // contactPoint is on surface of sphereA
collision->_contactPoint = sphereA->getPosition() + (sign * sphereA->getRadius()) * capsuleAxis; collision->_contactPoint = sphereA->getPosition() + (sign * sphereA->getRadius()) * capsuleAxis;
collision->_type = COLLISION_TYPE_UNKNOWN;
} }
return true; return true;
} }
@ -215,6 +218,7 @@ bool spherePlane(const SphereShape* sphereA, const PlaneShape* planeB, Collision
} }
collision->_penetration = penetration; collision->_penetration = penetration;
collision->_contactPoint = sphereA->getPosition() + sphereA->getRadius() * glm::normalize(penetration); collision->_contactPoint = sphereA->getPosition() + sphereA->getRadius() * glm::normalize(penetration);
collision->_type = COLLISION_TYPE_UNKNOWN;
return true; return true;
} }
return false; return false;
@ -264,6 +268,7 @@ bool capsuleSphere(const CapsuleShape* capsuleA, const SphereShape* sphereB, Col
collision->_penetration = (radialDistance - totalRadius) * radialAxis; // points from A into B collision->_penetration = (radialDistance - totalRadius) * radialAxis; // points from A into B
// contactPoint is on surface of capsuleA // contactPoint is on surface of capsuleA
collision->_contactPoint = closestApproach - capsuleA->getRadius() * radialAxis; collision->_contactPoint = closestApproach - capsuleA->getRadius() * radialAxis;
collision->_type = COLLISION_TYPE_UNKNOWN;
} else { } else {
// A is on B's axis, so the penetration is undefined... // A is on B's axis, so the penetration is undefined...
if (absAxialDistance > capsuleA->getHalfHeight()) { if (absAxialDistance > capsuleA->getHalfHeight()) {
@ -284,6 +289,7 @@ bool capsuleSphere(const CapsuleShape* capsuleA, const SphereShape* sphereB, Col
collision->_penetration = (sign * (totalRadius + capsuleA->getHalfHeight() - absAxialDistance)) * capsuleAxis; collision->_penetration = (sign * (totalRadius + capsuleA->getHalfHeight() - absAxialDistance)) * capsuleAxis;
// contactPoint is on surface of sphereA // contactPoint is on surface of sphereA
collision->_contactPoint = closestApproach + (sign * capsuleA->getRadius()) * capsuleAxis; collision->_contactPoint = closestApproach + (sign * capsuleA->getRadius()) * capsuleAxis;
collision->_type = COLLISION_TYPE_UNKNOWN;
} }
} }
return true; return true;
@ -355,6 +361,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
collision->_penetration = BA * (totalRadius - distance); collision->_penetration = BA * (totalRadius - distance);
// contactPoint is on surface of A // contactPoint is on surface of A
collision->_contactPoint = centerA + distanceA * axisA + capsuleA->getRadius() * BA; collision->_contactPoint = centerA + distanceA * axisA + capsuleA->getRadius() * BA;
collision->_type = COLLISION_TYPE_UNKNOWN;
return true; return true;
} }
} else { } else {
@ -420,6 +427,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
// average the internal pair, and then do the math from centerB // average the internal pair, and then do the math from centerB
collision->_contactPoint = centerB + (0.5f * (points[1] + points[2])) * axisB collision->_contactPoint = centerB + (0.5f * (points[1] + points[2])) * axisB
+ (capsuleA->getRadius() - distance) * BA; + (capsuleA->getRadius() - distance) * BA;
collision->_type = COLLISION_TYPE_UNKNOWN;
return true; return true;
} }
} }
@ -439,6 +447,7 @@ bool capsulePlane(const CapsuleShape* capsuleA, const PlaneShape* planeB, Collis
collision->_penetration = penetration; collision->_penetration = penetration;
glm::vec3 deepestEnd = (glm::dot(start, glm::vec3(plane)) < glm::dot(end, glm::vec3(plane))) ? start : end; glm::vec3 deepestEnd = (glm::dot(start, glm::vec3(plane)) < glm::dot(end, glm::vec3(plane))) ? start : end;
collision->_contactPoint = deepestEnd + capsuleA->getRadius() * glm::normalize(penetration); collision->_contactPoint = deepestEnd + capsuleA->getRadius() * glm::normalize(penetration);
collision->_type = COLLISION_TYPE_UNKNOWN;
return true; return true;
} }
return false; return false;
@ -454,6 +463,7 @@ bool planeSphere(const PlaneShape* planeA, const SphereShape* sphereB, Collision
collision->_penetration = -penetration; collision->_penetration = -penetration;
collision->_contactPoint = sphereB->getPosition() + collision->_contactPoint = sphereB->getPosition() +
(sphereB->getRadius() / glm::length(penetration) - 1.0f) * penetration; (sphereB->getRadius() / glm::length(penetration) - 1.0f) * penetration;
collision->_type = COLLISION_TYPE_UNKNOWN;
return true; return true;
} }
return false; return false;
@ -472,6 +482,7 @@ bool planeCapsule(const PlaneShape* planeA, const CapsuleShape* capsuleB, Collis
collision->_penetration = -penetration; collision->_penetration = -penetration;
glm::vec3 deepestEnd = (glm::dot(start, glm::vec3(plane)) < glm::dot(end, glm::vec3(plane))) ? start : end; glm::vec3 deepestEnd = (glm::dot(start, glm::vec3(plane)) < glm::dot(end, glm::vec3(plane))) ? start : end;
collision->_contactPoint = deepestEnd + (capsuleB->getRadius() / glm::length(penetration) - 1.0f) * penetration; collision->_contactPoint = deepestEnd + (capsuleB->getRadius() / glm::length(penetration) - 1.0f) * penetration;
collision->_type = COLLISION_TYPE_UNKNOWN;
return true; return true;
} }
return false; return false;
@ -656,9 +667,15 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm::
direction = glm::normalize(direction); direction = glm::normalize(direction);
// compute collision details // compute collision details
collision->_type = COLLISION_TYPE_AACUBE;
collision->_floatData = cubeSide;
collision->_vecData = cubeCenter;
collision->_penetration = (halfCubeSide + sphereRadius - distance * glm::dot(BA, direction)) * direction; collision->_penetration = (halfCubeSide + sphereRadius - distance * glm::dot(BA, direction)) * direction;
collision->_contactPoint = sphereCenter + sphereRadius * direction; collision->_contactPoint = sphereCenter + sphereRadius * direction;
} }
collision->_type = COLLISION_TYPE_AACUBE;
collision->_floatData = cubeSide;
collision->_vecData = cubeCenter;
return true; return true;
} else if (sphereRadius + halfCubeSide > distance) { } else if (sphereRadius + halfCubeSide > distance) {
// NOTE: for cocentric approximation we collide sphere and cube as two spheres which means // NOTE: for cocentric approximation we collide sphere and cube as two spheres which means
@ -669,6 +686,10 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm::
collision->_penetration = (sphereRadius + halfCubeSide) * glm::vec3(0.0f, -1.0f, 0.0f); collision->_penetration = (sphereRadius + halfCubeSide) * glm::vec3(0.0f, -1.0f, 0.0f);
// contactPoint is on surface of A // contactPoint is on surface of A
collision->_contactPoint = sphereCenter + collision->_penetration; collision->_contactPoint = sphereCenter + collision->_penetration;
collision->_type = COLLISION_TYPE_AACUBE;
collision->_floatData = cubeSide;
collision->_vecData = cubeCenter;
return true; return true;
} }
} }