mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 09:37:29 +02:00
Merge pull request #2811 from AndrewMeadows/inertia
prevent avatar from getting trapped in voxel collisions
This commit is contained in:
commit
c6b4b7c250
10 changed files with 100 additions and 76 deletions
|
@ -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;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
|
#include <GeometryUtil.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
@ -63,6 +64,7 @@ MyAvatar::MyAvatar() :
|
||||||
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
||||||
_wasPushing(false),
|
_wasPushing(false),
|
||||||
_isPushing(false),
|
_isPushing(false),
|
||||||
|
_wasStuck(false),
|
||||||
_thrust(0.0f),
|
_thrust(0.0f),
|
||||||
_motorVelocity(0.0f),
|
_motorVelocity(0.0f),
|
||||||
_motorTimescale(DEFAULT_MOTOR_TIMESCALE),
|
_motorTimescale(DEFAULT_MOTOR_TIMESCALE),
|
||||||
|
@ -212,6 +214,8 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
if (_collisionGroups & COLLISION_GROUP_VOXELS) {
|
if (_collisionGroups & COLLISION_GROUP_VOXELS) {
|
||||||
updateCollisionWithVoxels(deltaTime, radius);
|
updateCollisionWithVoxels(deltaTime, radius);
|
||||||
|
} else {
|
||||||
|
_wasStuck = false;
|
||||||
}
|
}
|
||||||
if (_collisionGroups & COLLISION_GROUP_AVATARS) {
|
if (_collisionGroups & COLLISION_GROUP_AVATARS) {
|
||||||
updateCollisionWithAvatars(deltaTime);
|
updateCollisionWithAvatars(deltaTime);
|
||||||
|
@ -958,65 +962,48 @@ void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) {
|
||||||
static CollisionList myCollisions(64);
|
static CollisionList myCollisions(64);
|
||||||
|
|
||||||
void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) {
|
void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) {
|
||||||
|
const float MIN_STUCK_SPEED = 100.0f;
|
||||||
|
float speed = glm::length(_velocity);
|
||||||
|
if (speed > MIN_STUCK_SPEED) {
|
||||||
|
// don't even bother to try to collide against voxles when moving very fast
|
||||||
|
return;
|
||||||
|
}
|
||||||
myCollisions.clear();
|
myCollisions.clear();
|
||||||
const CapsuleShape& boundingShape = _skeletonModel.getBoundingShape();
|
const CapsuleShape& boundingShape = _skeletonModel.getBoundingShape();
|
||||||
if (Application::getInstance()->getVoxelTree()->findShapeCollisions(&boundingShape, myCollisions)) {
|
if (Application::getInstance()->getVoxelTree()->findShapeCollisions(&boundingShape, myCollisions)) {
|
||||||
const float VOXEL_ELASTICITY = 0.0f;
|
const float VOXEL_ELASTICITY = 0.0f;
|
||||||
const float VOXEL_DAMPING = 0.0f;
|
const float VOXEL_DAMPING = 0.0f;
|
||||||
|
float capsuleRadius = boundingShape.getRadius();
|
||||||
|
|
||||||
if (glm::length2(_gravity) > EPSILON) {
|
glm::vec3 totalPenetration(0.0f);
|
||||||
if (myCollisions.size() == 1) {
|
bool isStuck = false;
|
||||||
// trivial case
|
for (int i = 0; i < myCollisions.size(); ++i) {
|
||||||
CollisionInfo* collision = myCollisions[0];
|
CollisionInfo* collision = myCollisions[i];
|
||||||
applyHardCollision(collision->_penetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
|
float depth = glm::length(collision->_penetration);
|
||||||
_lastFloorContactPoint = collision->_contactPoint - collision->_penetration;
|
if (depth > capsuleRadius) {
|
||||||
} else {
|
isStuck = true;
|
||||||
// This is special collision handling for when walking on a voxel field which
|
if (_wasStuck) {
|
||||||
// prevents snagging at corners and seams.
|
glm::vec3 cubeCenter = collision->_vecData;
|
||||||
|
float cubeSide = collision->_floatData;
|
||||||
// sift through the collisions looking for one against the "floor"
|
float distance = glm::dot(boundingShape.getPosition() - cubeCenter, _worldUpDirection);
|
||||||
int floorIndex = 0;
|
if (distance < 0.0f) {
|
||||||
float distanceToFloor = 0.0f;
|
distance = fabsf(distance) + 0.5f * cubeSide;
|
||||||
float penetrationWithFloor = 0.0f;
|
|
||||||
for (int i = 0; i < myCollisions.size(); ++i) {
|
|
||||||
CollisionInfo* collision = myCollisions[i];
|
|
||||||
float distance = glm::dot(_gravity, collision->_contactPoint - _position);
|
|
||||||
if (distance > distanceToFloor) {
|
|
||||||
distanceToFloor = distance;
|
|
||||||
penetrationWithFloor = glm::dot(_gravity, collision->_penetration);
|
|
||||||
floorIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// step through the collisions again and apply each that is not redundant
|
|
||||||
glm::vec3 oldPosition = _position;
|
|
||||||
for (int i = 0; i < myCollisions.size(); ++i) {
|
|
||||||
CollisionInfo* collision = myCollisions[i];
|
|
||||||
if (i == floorIndex) {
|
|
||||||
applyHardCollision(collision->_penetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
|
|
||||||
_lastFloorContactPoint = collision->_contactPoint - collision->_penetration;
|
|
||||||
} else {
|
|
||||||
float distance = glm::dot(_gravity, collision->_contactPoint - oldPosition);
|
|
||||||
float penetration = glm::dot(_gravity, collision->_penetration);
|
|
||||||
if (fabsf(distance - distanceToFloor) > penetrationWithFloor || penetration > penetrationWithFloor) {
|
|
||||||
// resolution of the deepest penetration would not resolve this one
|
|
||||||
// so we apply the collision
|
|
||||||
applyHardCollision(collision->_penetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
distance += capsuleRadius + boundingShape.getHalfHeight();
|
||||||
|
totalPenetration = addPenetrations(totalPenetration, - distance * _worldUpDirection);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
totalPenetration = addPenetrations(totalPenetration, collision->_penetration);
|
||||||
// no gravity -- apply all collisions
|
|
||||||
for (int i = 0; i < myCollisions.size(); ++i) {
|
|
||||||
CollisionInfo* collision = myCollisions[i];
|
|
||||||
applyHardCollision(collision->_penetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
applyHardCollision(totalPenetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
|
||||||
|
_wasStuck = isStuck;
|
||||||
|
|
||||||
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
||||||
updateCollisionSound(myCollisions[0]->_penetration, deltaTime, VOXEL_COLLISION_FREQUENCY);
|
updateCollisionSound(myCollisions[0]->_penetration, deltaTime, VOXEL_COLLISION_FREQUENCY);
|
||||||
}
|
} else {
|
||||||
|
_wasStuck = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity, float damping) {
|
void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity, float damping) {
|
||||||
|
|
|
@ -125,6 +125,7 @@ private:
|
||||||
|
|
||||||
bool _wasPushing;
|
bool _wasPushing;
|
||||||
bool _isPushing;
|
bool _isPushing;
|
||||||
|
bool _wasStuck;
|
||||||
glm::vec3 _thrust; // final acceleration from outside sources for the current frame
|
glm::vec3 _thrust; // final acceleration from outside sources for the current frame
|
||||||
|
|
||||||
glm::vec3 _motorVelocity; // intended velocity of avatar motion
|
glm::vec3 _motorVelocity; // intended velocity of avatar motion
|
||||||
|
|
|
@ -789,9 +789,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: ;
|
||||||
|
@ -805,9 +805,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1256,15 +1256,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();
|
||||||
}
|
}
|
||||||
|
@ -1272,12 +1272,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) {
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
#include <StreamUtils.h>
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
#include <VoxelConstants.h>
|
#include <VoxelConstants.h>
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,6 @@ typedef unsigned long long quint64;
|
||||||
|
|
||||||
#include <CollisionInfo.h>
|
#include <CollisionInfo.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <StreamUtils.h>
|
|
||||||
|
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -653,12 +664,19 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm::
|
||||||
glm::vec3 direction;
|
glm::vec3 direction;
|
||||||
BA /= maxBA;
|
BA /= maxBA;
|
||||||
glm::modf(BA, direction);
|
glm::modf(BA, direction);
|
||||||
direction = glm::normalize(direction);
|
float lengthDirection = glm::length(direction);
|
||||||
|
direction /= lengthDirection;
|
||||||
|
|
||||||
// compute collision details
|
// compute collision details
|
||||||
collision->_penetration = (halfCubeSide + sphereRadius - distance * glm::dot(BA, direction)) * direction;
|
collision->_type = COLLISION_TYPE_AACUBE;
|
||||||
|
collision->_floatData = cubeSide;
|
||||||
|
collision->_vecData = cubeCenter;
|
||||||
|
collision->_penetration = (halfCubeSide * lengthDirection + sphereRadius - maxBA * 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 +687,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue