void VerletShapeTests::sphereMissesSphere() { // non-overlapping spheres of unequal size float radiusA = 7.0f; float radiusB = 3.0f; float alpha = 1.2f; float beta = 1.3f; glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f)); float offsetDistance = alpha * radiusA + beta * radiusB; // create points for the sphere centers VerletPoint points[2]; // give pointers to the spheres VerletSphereShape sphereA(radiusA, (points + 0)); VerletSphereShape sphereB(radiusB, (points + 1)); // set the positions of the spheres by slamming the points directly points[0]._position = origin; points[1]._position = offsetDistance * offsetDirection; CollisionList collisions(16); // collide A to B... { bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // collide B to A... { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // also test shapeShape { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } if (collisions.size() > 0) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected empty collision list but size is " << collisions.size() << std::endl; } }
void ShapeColliderTests::sphereMissesSphere() { // non-overlapping spheres of unequal size float radiusA = 7.f; float radiusB = 3.f; float alpha = 1.2f; float beta = 1.3f; glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.f, 2.f, 3.f)); float offsetDistance = alpha * radiusA + beta * radiusB; SphereShape sphereA(radiusA, origin); SphereShape sphereB(radiusB, offsetDistance * offsetDirection); CollisionList collisions(16); // collide A to B... { bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // collide B to A... { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // also test shapeShape { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } if (collisions.size() > 0) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected empty collision list but size is " << collisions.size() << std::endl; } }
void ShapeColliderTests::sphereTouchesSphere() { // overlapping spheres of unequal size float radiusA = 7.f; float radiusB = 3.f; float alpha = 0.2f; float beta = 0.3f; glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.f, 2.f, 3.f)); float offsetDistance = alpha * radiusA + beta * radiusB; float expectedPenetrationDistance = (1.f - alpha) * radiusA + (1.f - beta) * radiusB; glm::vec3 expectedPenetration = expectedPenetrationDistance * offsetDirection; SphereShape sphereA(radiusA, origin); SphereShape sphereB(radiusB, offsetDistance * offsetDirection); CollisionList collisions(16); int numCollisions = 0; // collide A to B... { bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions); if (!touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should touch" << std::endl; } else { ++numCollisions; } // verify state of collisions if (numCollisions != collisions.size()) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected collisions size of " << numCollisions << " but actual size is " << collisions.size() << std::endl; } CollisionInfo* collision = collisions.getCollision(numCollisions - 1); if (!collision) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: null collision" << std::endl; } // penetration points from sphereA into sphereB float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of sphereA glm::vec3 AtoB = sphereB.getPosition() - sphereA.getPosition(); glm::vec3 expectedContactPoint = sphereA.getPosition() + radiusA * glm::normalize(AtoB); inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } // collide B to A... { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (!touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into sphereB CollisionInfo* collision = collisions.getCollision(numCollisions - 1); float inaccuracy = glm::length(collision->_penetration + expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of sphereA glm::vec3 BtoA = sphereA.getPosition() - sphereB.getPosition(); glm::vec3 expectedContactPoint = sphereB.getPosition() + radiusB * glm::normalize(BtoA); inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } }