mirror of
https://github.com/JulianGro/overte.git
synced 2025-05-29 06:01:26 +02:00
stubbery for processing collisions
PhysicsSimulation tells CollisionInfos to apply() themselves CollisionInfo knows how to apply() itself to affected shapes Shape gets _mass and some stubbed methods for accumulating movement VerletPoint gets movement accumulator
This commit is contained in:
parent
4a0ce7a9ae
commit
c7ad3da47d
7 changed files with 98 additions and 28 deletions
|
@ -11,6 +11,19 @@
|
||||||
|
|
||||||
#include "CollisionInfo.h"
|
#include "CollisionInfo.h"
|
||||||
|
|
||||||
|
#include "Shape.h"
|
||||||
|
|
||||||
|
CollisionInfo::CollisionInfo() :
|
||||||
|
_data(NULL),
|
||||||
|
_intData(0),
|
||||||
|
_shapeA(NULL),
|
||||||
|
_shapeB(NULL),
|
||||||
|
_damping(0.f),
|
||||||
|
_elasticity(1.f),
|
||||||
|
_contactPoint(0.f),
|
||||||
|
_penetration(0.f),
|
||||||
|
_addedVelocity(0.f) {
|
||||||
|
}
|
||||||
|
|
||||||
CollisionList::CollisionList(int maxSize) :
|
CollisionList::CollisionList(int maxSize) :
|
||||||
_maxSize(maxSize),
|
_maxSize(maxSize),
|
||||||
|
@ -18,6 +31,23 @@ CollisionList::CollisionList(int maxSize) :
|
||||||
_collisions.resize(_maxSize);
|
_collisions.resize(_maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollisionInfo::apply() {
|
||||||
|
assert(_shapeA);
|
||||||
|
// NOTE: Shape::computeEffectiveMass() has side effects: computes and caches partial Lagrangian coefficients
|
||||||
|
Shape* shapeA = const_cast<Shape*>(_shapeA);
|
||||||
|
float massA = shapeA->computeEffectiveMass(_penetration, _contactPoint);
|
||||||
|
float massB = Shape::MAX_MASS;
|
||||||
|
float totalMass = massA + massB;
|
||||||
|
if (_shapeB) {
|
||||||
|
Shape* shapeB = const_cast<Shape*>(_shapeB);
|
||||||
|
massB = shapeB->computeEffectiveMass(-_penetration, _contactPoint - _penetration);
|
||||||
|
totalMass = massA + massB;
|
||||||
|
shapeB->accumulateDelta(massA / totalMass, -_penetration);
|
||||||
|
}
|
||||||
|
// NOTE: Shape::accumulateDelta() uses the coefficients from previous call to Shape::computeEffectiveMass()
|
||||||
|
shapeA->accumulateDelta(massB / totalMass, _penetration);
|
||||||
|
}
|
||||||
|
|
||||||
CollisionInfo* CollisionList::getNewCollision() {
|
CollisionInfo* CollisionList::getNewCollision() {
|
||||||
// return pointer to existing CollisionInfo, or NULL of list is full
|
// return pointer to existing CollisionInfo, or NULL of list is full
|
||||||
return (_size < _maxSize) ? &(_collisions[_size++]) : NULL;
|
return (_size < _maxSize) ? &(_collisions[_size++]) : NULL;
|
||||||
|
|
|
@ -32,38 +32,18 @@ const quint32 VALID_COLLISION_GROUPS = 0x0f;
|
||||||
|
|
||||||
class CollisionInfo {
|
class CollisionInfo {
|
||||||
public:
|
public:
|
||||||
CollisionInfo()
|
CollisionInfo();
|
||||||
: _data(NULL),
|
|
||||||
_intData(0),
|
|
||||||
_shapeA(NULL),
|
|
||||||
_shapeB(NULL),
|
|
||||||
_damping(0.f),
|
|
||||||
_elasticity(1.f),
|
|
||||||
_contactPoint(0.f),
|
|
||||||
_penetration(0.f),
|
|
||||||
_addedVelocity(0.f) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CollisionInfo(qint32 type)
|
|
||||||
: _data(NULL),
|
|
||||||
_intData(0),
|
|
||||||
_shapeA(NULL),
|
|
||||||
_shapeB(NULL),
|
|
||||||
_damping(0.f),
|
|
||||||
_elasticity(1.f),
|
|
||||||
_contactPoint(0.f),
|
|
||||||
_penetration(0.f),
|
|
||||||
_addedVelocity(0.f) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~CollisionInfo() {}
|
~CollisionInfo() {}
|
||||||
|
|
||||||
// the value of the *Data fields depend on the type
|
// TODO: Andrew to get rid of these data members
|
||||||
void* _data;
|
void* _data;
|
||||||
int _intData;
|
int _intData;
|
||||||
float _floatData;
|
float _floatData;
|
||||||
glm::vec3 _vecData;
|
glm::vec3 _vecData;
|
||||||
|
|
||||||
|
/// accumulates position changes for the shapes in this collision to resolve penetration
|
||||||
|
void apply();
|
||||||
|
|
||||||
Shape* getShapeA() const { return const_cast<Shape*>(_shapeA); }
|
Shape* getShapeA() const { return const_cast<Shape*>(_shapeA); }
|
||||||
Shape* getShapeB() const { return const_cast<Shape*>(_shapeB); }
|
Shape* getShapeB() const { return const_cast<Shape*>(_shapeB); }
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,7 @@ bool PhysicsEntity::findSphereCollisions(const glm::vec3& sphereCenter, float sp
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsEntity::findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions) {
|
bool PhysicsEntity::findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions) {
|
||||||
|
// TODO: Andrew to reimplement this or make it unecessary
|
||||||
bool collided = false;
|
bool collided = false;
|
||||||
PlaneShape planeShape(plane);
|
PlaneShape planeShape(plane);
|
||||||
for (int i = 0; i < _shapes.size(); i++) {
|
for (int i = 0; i < _shapes.size(); i++) {
|
||||||
|
|
|
@ -189,7 +189,25 @@ void PhysicsSimulation::computeCollisions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSimulation::processCollisions() {
|
void PhysicsSimulation::processCollisions() {
|
||||||
// TODO: Andrew to implement this
|
// walk all collisions, accumulate movement on shapes, and build a list of affected shapes
|
||||||
|
QSet<Shape*> shapes;
|
||||||
|
int numCollisions = _collisionList.size();
|
||||||
|
for (int i = 0; i < numCollisions; ++i) {
|
||||||
|
CollisionInfo* collision = _collisionList.getCollision(i);
|
||||||
|
collision->apply();
|
||||||
|
// there is always a shapeA
|
||||||
|
shapes.insert(collision->getShapeA());
|
||||||
|
// but need to check for valid shapeB
|
||||||
|
if (collision->_shapeB) {
|
||||||
|
shapes.insert(collision->getShapeB());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// walk all affected shapes and apply accumulated movement
|
||||||
|
QSet<Shape*>::const_iterator shapeItr = shapes.constBegin();
|
||||||
|
while (shapeItr != shapes.constEnd()) {
|
||||||
|
(*shapeItr)->applyAccumulatedDelta();
|
||||||
|
++shapeItr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSimulation::enforceConstraints(float minError, int maxIterations, quint64 maxUsec) {
|
void PhysicsSimulation::enforceConstraints(float minError, int maxIterations, quint64 maxUsec) {
|
||||||
|
|
|
@ -16,6 +16,20 @@
|
||||||
#include "SharedUtil.h"
|
#include "SharedUtil.h"
|
||||||
#include "SphereShape.h"
|
#include "SphereShape.h"
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// VerletPoint
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void VerletPoint::accumulatePush(const glm::vec3& delta) {
|
||||||
|
_accumulatedPush += delta;
|
||||||
|
++_numPushes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerletPoint::applyAccumulatedPush() {
|
||||||
|
_lastPosition = _position;
|
||||||
|
_position += _accumulatedPush / (float)_numPushes;
|
||||||
|
_numPushes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// FixedConstraint
|
// FixedConstraint
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -21,10 +21,18 @@ class Shape;
|
||||||
|
|
||||||
class VerletPoint {
|
class VerletPoint {
|
||||||
public:
|
public:
|
||||||
VerletPoint() : _position(0.0f), _lastPosition(0.0f), _mass(0.0f) {}
|
VerletPoint() : _position(0.0f), _lastPosition(0.0f), _mass(0.0f), _accumulatedPush(0.0f), _numPushes(0) {}
|
||||||
|
|
||||||
|
void accumulatePush(const glm::vec3& delta);
|
||||||
|
void applyAccumulatedPush();
|
||||||
|
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
glm::vec3 _lastPosition;
|
glm::vec3 _lastPosition;
|
||||||
float _mass;
|
float _mass;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
glm::vec3 _accumulatedPush;
|
||||||
|
int _numPushes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Constraint {
|
class Constraint {
|
||||||
|
|
|
@ -19,6 +19,8 @@ class PhysicsEntity;
|
||||||
|
|
||||||
class Shape {
|
class Shape {
|
||||||
public:
|
public:
|
||||||
|
static const float MAX_MASS = 1.0e18f; // something less than sqrt(FLT_MAX)
|
||||||
|
|
||||||
enum Type{
|
enum Type{
|
||||||
UNKNOWN_SHAPE = 0,
|
UNKNOWN_SHAPE = 0,
|
||||||
SPHERE_SHAPE,
|
SPHERE_SHAPE,
|
||||||
|
@ -27,7 +29,7 @@ public:
|
||||||
LIST_SHAPE
|
LIST_SHAPE
|
||||||
};
|
};
|
||||||
|
|
||||||
Shape() : _type(UNKNOWN_SHAPE), _owningEntity(NULL), _boundingRadius(0.f), _translation(0.f), _rotation() { }
|
Shape() : _type(UNKNOWN_SHAPE), _owningEntity(NULL), _boundingRadius(0.f), _translation(0.f), _rotation(), _mass(MAX_MASS) { }
|
||||||
virtual ~Shape() {}
|
virtual ~Shape() {}
|
||||||
|
|
||||||
int getType() const { return _type; }
|
int getType() const { return _type; }
|
||||||
|
@ -43,8 +45,24 @@ public:
|
||||||
virtual void setTranslation(const glm::vec3& translation) { _translation = translation; }
|
virtual void setTranslation(const glm::vec3& translation) { _translation = translation; }
|
||||||
virtual const glm::vec3& getTranslation() const { return _translation; }
|
virtual const glm::vec3& getTranslation() const { return _translation; }
|
||||||
|
|
||||||
|
virtual void setMass(float mass) { _mass = mass; }
|
||||||
|
virtual float getMass() const { return _mass; }
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const = 0;
|
virtual bool findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const = 0;
|
||||||
|
|
||||||
|
/// \param penetration of collision
|
||||||
|
/// \param contactPoint of collision
|
||||||
|
/// \return the effective mass for the collision
|
||||||
|
/// For most shapes has side effects: computes and caches the partial Lagrangian coefficients which will be
|
||||||
|
/// used in the next accumulateDelta() call.
|
||||||
|
virtual float computeEffectiveMass(const glm::vec3& penetration, const glm::vec3& contactPoint) { return _mass; }
|
||||||
|
|
||||||
|
/// \param relativeMassFactor the final ingredient for partial Lagrangian coefficients from computeEffectiveMass()
|
||||||
|
/// \param penetration the delta movement
|
||||||
|
virtual void accumulateDelta(float relativeMassFactor, const glm::vec3& penetration) {}
|
||||||
|
|
||||||
|
virtual void applyAccumulatedDelta() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// these ctors are protected (used by derived classes only)
|
// these ctors are protected (used by derived classes only)
|
||||||
Shape(Type type) : _type(type), _owningEntity(NULL), _boundingRadius(0.f), _translation(0.f), _rotation() {}
|
Shape(Type type) : _type(type), _owningEntity(NULL), _boundingRadius(0.f), _translation(0.f), _rotation() {}
|
||||||
|
@ -62,6 +80,7 @@ protected:
|
||||||
float _boundingRadius;
|
float _boundingRadius;
|
||||||
glm::vec3 _translation;
|
glm::vec3 _translation;
|
||||||
glm::quat _rotation;
|
glm::quat _rotation;
|
||||||
|
float _mass;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Shape_h
|
#endif // hifi_Shape_h
|
||||||
|
|
Loading…
Reference in a new issue