Store information needed to generate contacts

This commit is contained in:
James Lambert 2022-05-31 18:35:57 -06:00
parent 4ccb63dfc4
commit a264c3af3e
7 changed files with 96 additions and 102 deletions

View file

@ -68,48 +68,22 @@ void collisionObjectUpdateBB(struct CollisionObject* object) {
}
}
void minkowsiSumAgainstQuadInit(struct MinkowsiSumAgainstQuad* sumData, struct CollisionObject* object, struct CollisionQuad* quad) {
sumData->collisionObject = object;
sumData->quad= quad;
}
void minkowsiSumAgainstQuad(void* data, struct Vector3* direction, struct Vector3* output) {
struct CollisionQuad* quad = (struct CollisionQuad*)data;
*output = quad->corner;
void minkowsiSumAgainstQuadSum(void* data, struct Vector3* direction, struct Vector3* output) {
struct MinkowsiSumAgainstQuad* collisionData = (struct MinkowsiSumAgainstQuad*)data;
collisionData->collisionObject->collider->callbacks->minkowsiSum(collisionData->collisionObject->collider->data, &collisionData->collisionObject->body->rotationBasis, direction, output);
vector3Add(output, &collisionData->collisionObject->body->transform.position, output);
struct Vector3 quadSum = collisionData->quad->corner;
if (vector3Dot(&collisionData->quad->edgeA, direction) < 0.0f) {
vector3AddScaled(&quadSum, &collisionData->quad->edgeA, collisionData->quad->edgeALength, &quadSum);
if (vector3Dot(&quad->edgeA, direction) > 0.0f) {
vector3AddScaled(output, &quad->edgeA, quad->edgeALength, output);
}
if (vector3Dot(&collisionData->quad->edgeB, direction) < 0.0f) {
vector3AddScaled(&quadSum, &collisionData->quad->edgeB, collisionData->quad->edgeBLength, &quadSum);
if (vector3Dot(&quad->edgeB, direction) > 0.0f) {
vector3AddScaled(output, &quad->edgeB, quad->edgeBLength, output);
}
vector3Sub(output, &quadSum, output);
}
void minkowsiSumAgainstObjectsInit(struct MinkowsiSumAgainstObjects* sumData, struct CollisionObject* a, struct CollisionObject* b) {
sumData->collisionObjectA = a;
sumData->collisionObjectB = b;
}
// data should be of type struct MinkowsiSumAgainstObjects
void minkowsiSumAgainstObjects(void* data, struct Vector3* direction, struct Vector3* output) {
struct MinkowsiSumAgainstObjects* collisionData = (struct MinkowsiSumAgainstObjects*)data;
collisionData->collisionObjectA->collider->callbacks->minkowsiSum(collisionData->collisionObjectA->collider->data, &collisionData->collisionObjectA->body->rotationBasis, direction, output);
vector3Add(output, &collisionData->collisionObjectA->body->transform.position, output);
struct Vector3 bResult;
struct Vector3 oppositeDir;
vector3Negate(direction, &oppositeDir);
collisionData->collisionObjectB->collider->callbacks->minkowsiSum(collisionData->collisionObjectB->collider->data, &collisionData->collisionObjectB->body->rotationBasis, &oppositeDir, output);
vector3Add(output, &collisionData->collisionObjectB->body->transform.position, &bResult);
vector3Sub(output, &bResult, output);
void minkowsiSumAgainstObject(void* data, struct Vector3* direction, struct Vector3* output) {
struct CollisionObject* object = (struct CollisionObject*)data;
object->collider->callbacks->minkowsiSum(object->collider->data, &object->body->rotationBasis, direction, output);
vector3Add(output, &object->body->transform.position, output);
}

View file

@ -18,25 +18,11 @@ void collisionObjectCollideWithQuad(struct CollisionObject* object, struct Colli
void collisionObjectUpdateBB(struct CollisionObject* object);
struct MinkowsiSumAgainstQuad {
struct CollisionObject* collisionObject;
struct CollisionQuad* quad;
};
// data should be of type struct CollisionQuad
void minkowsiSumAgainstQuad(void* data, struct Vector3* direction, struct Vector3* output);
void minkowsiSumAgainstQuadInit(struct MinkowsiSumAgainstQuad* sumData, struct CollisionObject* object, struct CollisionQuad* quad);
// data should be of type struct MinkowsiSumAgainstQuad
void minkowsiSumAgainstQuadSum(void* data, struct Vector3* direction, struct Vector3* output);
struct MinkowsiSumAgainstObjects {
struct CollisionObject* collisionObjectA;
struct CollisionObject* collisionObjectB;
};
void minkowsiSumAgainstObjectsInit(struct MinkowsiSumAgainstObjects* sumData, struct CollisionObject* a, struct CollisionObject* b);
// data should be of type struct MinkowsiSumAgainstObjects
void minkowsiSumAgainstObjects(void* data, struct Vector3* direction, struct Vector3* output);
// data should be of type struct CollisionObject
void minkowsiSumAgainstObject(void* data, struct Vector3* direction, struct Vector3* output);
#endif

View file

@ -392,19 +392,27 @@ int collisionSceneTestMinkowsiSum(struct CollisionObject* object) {
return 0;
}
struct MinkowsiSumAgainstQuad quadSum;
quadSum.collisionObject = object;
struct Simplex simplex;
short colliderIndices[MAX_COLLIDERS];
int quadCount = collisionObjectRoomColliders(&gCollisionScene.world->rooms[object->body->currentRoom], &object->boundingBox, colliderIndices);
for (int i = 0; i < quadCount; ++i) {
quadSum.quad = gCollisionScene.quads[colliderIndices[i]].collider->data;
struct CollisionQuad* quad = gCollisionScene.quads[colliderIndices[i]].collider->data;
if (box3DHasOverlap(&object->boundingBox, &gCollisionScene.quads[colliderIndices[i]].boundingBox) && gjkCheckForOverlap(&simplex, &quadSum, minkowsiSumAgainstQuadSum, &quadSum.quad->plane.normal)) {
if (box3DHasOverlap(&object->boundingBox, &gCollisionScene.quads[colliderIndices[i]].boundingBox) &&
gjkCheckForOverlap(
&simplex,
object, minkowsiSumAgainstObject,
quad, minkowsiSumAgainstQuad,
&quad->plane.normal)) {
struct EpaResult result;
epaSolve(&simplex, &quadSum, minkowsiSumAgainstQuadSum, &result);
epaSolve(
&simplex,
object, minkowsiSumAgainstObject,
quad, minkowsiSumAgainstQuad,
&result
);
return 1;
}
}

View file

@ -16,22 +16,20 @@ struct SimplexTriangle {
struct ExpandingSimplex {
struct Vector3 points[MAX_SIMPLEX_POINTS];
struct Vector3 aPoints[MAX_SIMPLEX_POINTS];
struct Vector3 bPoints[MAX_SIMPLEX_POINTS];
unsigned pointCount;
struct SimplexTriangle triangles[MAX_SIMPLEX_TRIANGLES];
unsigned triangleCount;
unsigned char triangleHeap[MAX_SIMPLEX_TRIANGLES];
};
int expandingSimplexAddPoint(struct ExpandingSimplex* simplex, struct Vector3* point) {
if (simplex->pointCount == MAX_SIMPLEX_POINTS) {
return -1;
}
void expandingSimplexAddPoint(struct ExpandingSimplex* simplex, struct Vector3* aPoint, struct Vector3* bPoint, struct Vector3* pointDiff) {
int result = simplex->pointCount;
simplex->points[result] = *point;
simplex->aPoints[result] = *aPoint;
simplex->bPoints[result] = *bPoint;
simplex->points[result] = *pointDiff;
++simplex->pointCount;
return result;
}
void expandingSimplexTriangleInit(struct ExpandingSimplex* simplex, int a, int b, int c, struct SimplexTriangle* triangle) {
@ -143,10 +141,9 @@ void expandingSimplexInit(struct ExpandingSimplex* expandingSimplex, struct Simp
expandingSimplex->triangleCount = 0;
expandingSimplex->pointCount = 0;
expandingSimplexAddPoint(expandingSimplex, &simplex->points[0]);
expandingSimplexAddPoint(expandingSimplex, &simplex->points[1]);
expandingSimplexAddPoint(expandingSimplex, &simplex->points[2]);
expandingSimplexAddPoint(expandingSimplex, &simplex->points[3]);
for (int i = 0; i < 4; ++i) {
expandingSimplexAddPoint(expandingSimplex, &simplex->objectAPoint[i], &simplex->objectBPoint[i], &simplex->points[i]);
}
expandingSimplexAddTriangle(expandingSimplex, 0, 1, 2);
expandingSimplexAddTriangle(expandingSimplex, 2, 1, 3);
@ -154,9 +151,7 @@ void expandingSimplexInit(struct ExpandingSimplex* expandingSimplex, struct Simp
expandingSimplexAddTriangle(expandingSimplex, 1, 0, 3);
}
int expandingSimplexExpand(struct ExpandingSimplex* expandingSimplex, struct Vector3* newPoint) {
int newPointIndex = expandingSimplexAddPoint(expandingSimplex, newPoint);
int expandingSimplexExpand(struct ExpandingSimplex* expandingSimplex, int newPointIndex) {
if (newPointIndex == -1) {
return 0;
}
@ -177,26 +172,39 @@ int expandingSimplexExpand(struct ExpandingSimplex* expandingSimplex, struct Vec
return 1;
}
void epaSolve(struct Simplex* startingSimplex, void* data, MinkowsiSum sum, struct EpaResult* result) {
void epaSolve(struct Simplex* startingSimplex, void* objectA, MinkowsiSum objectASum, void* objectB, MinkowsiSum objectBSum, struct EpaResult* result) {
struct ExpandingSimplex* simplex = stackMalloc(sizeof(struct ExpandingSimplex));
expandingSimplexInit(simplex, startingSimplex);
struct Vector3 nextPoint;
struct SimplexTriangle* closestFace = NULL;
float projection = 0.0f;
int i;
for (i = 0; i < MAX_ITERATIONS; ++i) {
closestFace = expandingSimplexClosestFace(simplex);
sum(data, &closestFace->normal, &nextPoint);
struct Vector3 reverseNormal;
projection = vector3Dot(&nextPoint, &closestFace->normal);
closestFace = expandingSimplexClosestFace(simplex);
int nextIndex = simplex->pointCount;
struct Vector3* aPoint = &simplex->aPoints[nextIndex];
struct Vector3* bPoint = &simplex->bPoints[nextIndex];
objectASum(objectA, &closestFace->normal, aPoint);
vector3Negate(&closestFace->normal, &reverseNormal);
objectBSum(objectB, &reverseNormal, bPoint);
vector3Sub(aPoint, bPoint, &simplex->points[nextIndex]);
projection = vector3Dot(&simplex->points[nextIndex], &closestFace->normal);
if ((projection - closestFace->distanceToOrigin) < 0.00000001f) {
break;
}
if (!expandingSimplexExpand(simplex, &nextPoint)) {
++simplex->pointCount;
if (!expandingSimplexExpand(simplex, nextIndex)) {
break;
}
}

View file

@ -8,6 +8,6 @@ struct EpaResult {
float penetration;
};
void epaSolve(struct Simplex* startingSimplex, void* data, MinkowsiSum sum, struct EpaResult* result);
void epaSolve(struct Simplex* startingSimplex, void* objectA, MinkowsiSum objectASum, void* objectB, MinkowsiSum objectBSum, struct EpaResult* result);
#endif

View file

@ -1,20 +1,23 @@
#include "gjk.h"
void simplexInit(struct Simplex* simplex, struct Vector3* firstPoint) {
simplex->nPoints = 1;
simplex->points[0] = *firstPoint;
void simplexInit(struct Simplex* simplex) {
simplex->nPoints = 0;
}
int simplexAddPoint(struct Simplex* simplex, struct Vector3* point) {
struct Vector3* simplexAddPoint(struct Simplex* simplex, struct Vector3* aPoint, struct Vector3* bPoint) {
if (simplex->nPoints == MAX_SIMPLEX_SIZE) {
// SHOULD never happen, but just in case
return 0;
}
simplex->points[simplex->nPoints] = *point;
int index = simplex->nPoints;
simplex->objectAPoint[index] = *aPoint;
simplex->objectBPoint[index] = *bPoint;
vector3Sub(&simplex->objectAPoint[index], &simplex->objectBPoint[index], &simplex->points[index]);
++simplex->nPoints;
return 1;
return &simplex->points[index];
}
int simplexCheck(struct Simplex* simplex, struct Vector3* nextDirection) {
@ -155,30 +158,43 @@ int simplexCheck(struct Simplex* simplex, struct Vector3* nextDirection) {
#define MAX_GJK_ITERATIONS 10
int gjkCheckForOverlap(struct Simplex* simplex, void* data, MinkowsiSum sum, struct Vector3* firstDirection) {
struct Vector3 nextPoint;
int gjkCheckForOverlap(struct Simplex* simplex, void* objectA, MinkowsiSum objectASum, void* objectB, MinkowsiSum objectBSum, struct Vector3* firstDirection) {
struct Vector3 aPoint;
struct Vector3 bPoint;
struct Vector3 nextDirection;
simplexInit(simplex);
if (vector3IsZero(firstDirection)) {
sum(data, &gRight, &nextPoint);
objectASum(objectA, &gRight, &aPoint);
vector3Negate(&gRight, &nextDirection);
objectBSum(objectB, &nextDirection, &bPoint);
simplexAddPoint(simplex, &aPoint, &bPoint);
} else {
sum(data, firstDirection, &nextPoint);
objectASum(objectA, firstDirection, &aPoint);
vector3Negate(firstDirection, &nextDirection);
objectBSum(objectB, &nextDirection, &bPoint);
simplexAddPoint(simplex, &aPoint, &bPoint);
}
simplexInit(simplex, &nextPoint);
for (int iteration = 0; iteration < MAX_GJK_ITERATIONS; ++iteration) {
sum(data, &nextDirection, &nextPoint);
struct Vector3 reverseDirection;
vector3Negate(&nextDirection, &reverseDirection);
objectASum(objectA, &nextDirection, &aPoint);
objectBSum(objectB, &reverseDirection, &bPoint);
struct Vector3* addedPoint = simplexAddPoint(simplex, &aPoint, &bPoint);
if (!addedPoint) {
return 0;
}
if (vector3Dot(&nextPoint, &nextDirection) <= 0.0f) {
if (vector3Dot(addedPoint, &nextDirection) <= 0.0f) {
return 0;
}
if (!simplexAddPoint(simplex, &nextPoint)) {
return 0;
}
if (simplexCheck(simplex, &nextDirection)) {
return 1;

View file

@ -9,13 +9,15 @@ typedef void (*MinkowsiSum)(void* data, struct Vector3* direction, struct Vector
struct Simplex {
struct Vector3 points[MAX_SIMPLEX_SIZE];
struct Vector3 objectAPoint[MAX_SIMPLEX_SIZE];
struct Vector3 objectBPoint[MAX_SIMPLEX_SIZE];
short nPoints;
};
void simplexInit(struct Simplex* simplex, struct Vector3* firstPoint);
int simplexAddPoint(struct Simplex* simplex, struct Vector3* point);
void simplexInit(struct Simplex* simplex);
struct Vector3* simplexAddPoint(struct Simplex* simplex, struct Vector3* aPoint, struct Vector3* bPoint);
int simplexCheck(struct Simplex* simplex, struct Vector3* nextDirection);
int gjkCheckForOverlap(struct Simplex* simplex, void* data, MinkowsiSum sum, struct Vector3* firstDirection);
int gjkCheckForOverlap(struct Simplex* simplex, void* objectA, MinkowsiSum objectASum, void* objectB, MinkowsiSum objectBSum, struct Vector3* firstDirection);
#endif