Esempio n. 1
0
void ContactGenerator::box_halfspace(const CollisionShape &a, const RigidBody &rbA, const CollisionShape &b, const RigidBody &rbB, ContactManifold &contactManifold)
{
	// Make sure we have contacts left and Check if they're the right shapes.
	if (a.getShapeType() != SHAPE_BOX || b.getShapeType() != SHAPE_HALFSPACE ) { return; }

	// then typecast their appropriate shapes
	const ShapeBox& box = (const ShapeBox&)a;
	const ShapeHalfspace& halfspace = (const ShapeHalfspace&)b;

	const Vec3& boxHalfExtents = box.getHalfExtents();

	// generate a array of all of the box's vertices
	Vec3 boxVertex[8] = 
	{
		Vec3(-boxHalfExtents.x, -boxHalfExtents.y, -boxHalfExtents.z),
		Vec3(-boxHalfExtents.x, -boxHalfExtents.y, +boxHalfExtents.z),
		Vec3(-boxHalfExtents.x, +boxHalfExtents.y, -boxHalfExtents.z),
		Vec3(-boxHalfExtents.x, +boxHalfExtents.y, +boxHalfExtents.z),
		Vec3(+boxHalfExtents.x, -boxHalfExtents.y, -boxHalfExtents.z),
		Vec3(+boxHalfExtents.x, -boxHalfExtents.y, +boxHalfExtents.z),
		Vec3(+boxHalfExtents.x, +boxHalfExtents.y, -boxHalfExtents.z),
		Vec3(+boxHalfExtents.x, +boxHalfExtents.y, +boxHalfExtents.z),
	};

	const Transform& boxTransform = rbA.getTransform();

	// Apply collision object offset
	for (int i = 0; i < 8; i++)
	{
		boxVertex[i] = boxTransform * a.getOffset() * boxVertex[i];
	}

	// Calculate halfspace's position and normal
	Vec3 posHalfspace = b.getOffset().getPosition() + rbB.getPosition();
	Vec3 normHalfspace = rbB.getTransform() * b.getOffset() * Vec3(0.f, 1.f, 0.f, 0.f);

	// Check each vertice for intersection with the halfspace
	Scalar vertexDistance;

	unsigned int numContacts = 0;

	for (int i = 0; i < 8; i++)
	{
		vertexDistance = boxVertex[i].dot(normHalfspace) - posHalfspace.y;

		if(vertexDistance <= 0)
		{
			// Create contact data
			ContactPoint newContact;

			newContact.normal = normHalfspace;
			newContact.penetration = -vertexDistance;
			newContact.position = boxVertex[i] + newContact.normal*(newContact.penetration*0.5f);

			contactManifold.addContactPoint(newContact);
		}
	}

	return;
}
Esempio n. 2
0
void ContactGenerator::sphere_halfspace(const CollisionShape &a, const RigidBody &rbA, const CollisionShape &b, const RigidBody &rbB, ContactManifold &contactManifold)
{
	// Make sure we have contacts left and Check if they're the right shapes.
	if ( a.getShapeType() != SHAPE_SPHERE || b.getShapeType() != SHAPE_HALFSPACE ) { return; }

	// then typecast their appropriate shapes
	const ShapeSphere& sphere = (const ShapeSphere&)a;
	const ShapeHalfspace& halfspace = (const ShapeHalfspace&)b;

	// Get the positions and halfspace normal
	Vec3 posSphere = a.getOffset().getPosition() + rbA.getTransform().getPosition();
	Vec3 posHalfspace = a.getOffset().getPosition() + rbB.getTransform().getPosition();;
	Vec3 normHalfspace = rbB.getTransform() * b.getOffset() * Vec3(0.f, 1.f, 0.f, 0.f);

	// Find the distance from the plane to the sphere
	Scalar distance = normHalfspace.dot(posSphere) - sphere.getRadius() - (posHalfspace).y;

	// Check collision
	if(distance < 0)
	{
		// Create contact data
		ContactPoint newContact;

		newContact.normal = normHalfspace;
		newContact.position = posSphere + -newContact.normal*(sphere.getRadius() - newContact.penetration/2);
		newContact.penetration = -distance;

		contactManifold.addContactPoint(newContact);
	}

	return;
}
Esempio n. 3
0
void ContactGenerator::sphere_sphere(const CollisionShape &a, const RigidBody &rbA, const CollisionShape &b, const RigidBody &rbB, ContactManifold &contactManifold)
{
	// Make sure we have contacts left and Check if they're spheres.
	if ( a.getShapeType() != SHAPE_SPHERE || b.getShapeType() != SHAPE_SPHERE ) { return; }
	
	//  then typecast their shape to a sphere
	const ShapeSphere& shapeA = (const ShapeSphere&)a;
	const ShapeSphere& shapeB = (const ShapeSphere&)b;

	// Get the sphere positions
	Vec3 posA = a.getOffset().getPosition() + rbA.getPosition();
	Vec3 posB = b.getOffset().getPosition() + rbB.getPosition();

	// Find the vector between the two object
	Vec3 midLine = posA - posB;
	Scalar distance = midLine.length();

	// Check for collision
	if (distance <= 0.0f || distance >= shapeA.getRadius() + shapeB.getRadius())
	{
		return;
	}

	// Create contact data
	ContactPoint newContact;

	newContact.normal = midLine * ( ((Scalar)1.0) / distance );
	newContact.position = posA + (midLine * (Scalar)-0.5);
	newContact.penetration = (shapeA.getRadius() + shapeA.getRadius() - distance);

	contactManifold.addContactPoint(newContact);
}
Esempio n. 4
0
void ContactGenerator::box_box(const CollisionShape &a, const RigidBody &rbA, const CollisionShape &b, const RigidBody &rbB, ContactManifold &contactManifold)
{
	// Make sure we have contacts left and Check if they're boxes.
	if ( a.getShapeType() != SHAPE_BOX || b.getShapeType() != SHAPE_BOX ) { return; }

	// then typecast their appropriate shapes
	const ShapeBox& boxA = (const ShapeBox&)a;
	const ShapeBox& boxB = (const ShapeBox&)b;

	const Vec3& boxAHalfExtents = boxA.getHalfExtents();
	const Vec3& boxBHalfExtents = boxB.getHalfExtents();

	Transform boxATransform = rbA.getTransform() * a.getOffset();
	Transform boxBTransform = rbB.getTransform() * b.getOffset();

	// Vector between box centres.
	Vec3 separation = boxBTransform.getPosition() - boxATransform.getPosition();

	Scalar smallestPen = SCALAR_MAX;
	unsigned int bestPen = 0xffffffff;

	// Check each axis, keeping track of the axis with the smallest penetration.
	// Stops when if finds an axis without penetration.
	if (!tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(0), separation, 0, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(1), separation, 1, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(2), separation, 2, smallestPen, bestPen) ||

        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxBTransform.getAxisVector(0), separation, 3, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxBTransform.getAxisVector(1), separation, 4, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxBTransform.getAxisVector(2), separation, 5, smallestPen, bestPen) )
	{
		return;
	}

	unsigned bestSingleAxis = bestPen;

	if (!tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(0).cross(boxBTransform.getAxisVector(0)), separation,  6, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(0).cross(boxBTransform.getAxisVector(1)), separation,  7, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(0).cross(boxBTransform.getAxisVector(2)), separation,  8, smallestPen, bestPen) ||

        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(1).cross(boxBTransform.getAxisVector(0)), separation,  9, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(1).cross(boxBTransform.getAxisVector(1)), separation, 10, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(1).cross(boxBTransform.getAxisVector(2)), separation, 11, smallestPen, bestPen) ||

        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(2).cross(boxBTransform.getAxisVector(0)), separation, 12, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(2).cross(boxBTransform.getAxisVector(1)), separation, 13, smallestPen, bestPen) ||
        !tryAxis(boxA, boxATransform, boxB, boxBTransform, boxATransform.getAxisVector(2).cross(boxBTransform.getAxisVector(2)), separation, 14, smallestPen, bestPen) )
	{
		return;
	}

	// We've found a collision, and we know which of the axes gave the smallest penetration.
	if (bestPen < 3)
	{
		// Vertex of boxB in face of boxA
		// TODO: Do stuff
		//std::cout << bestPen << " Vertex of boxB in face of boxA\n";
		fillPointFaceBoxBox(boxA, boxATransform, boxB, boxBTransform, separation, contactManifold, bestPen, smallestPen, false);
		return;
	}
	else if (bestPen < 6)
	{
		// Vertex of boxA in face of boxB
		// TODO: Do stuff
		//std::cout << bestPen << " Vertex of boxA in face of boxB\n";
		fillPointFaceBoxBox(boxA, boxATransform, boxB, boxBTransform, -separation, contactManifold, bestPen-3, smallestPen, true);
		return;
	}
	else
	{
		// Edge Edge contact.
		//std::cout << "Colliding >= 6";
		//std::cout << bestPen << " Edge-Edge\n";

		// Find which axis.
		bestPen -= 6;
		unsigned int axisIndexA = bestPen / 3;
		unsigned int axisIndexB = bestPen % 3;
		Vec3 axisA = boxATransform.getAxisVector(axisIndexA);
		Vec3 axisB = boxBTransform.getAxisVector(axisIndexB);
		Vec3 axis = axisA.cross(axisB);
		axis.normalize();

		// Axis should point from box one to box two.
		if ( axis.dot(separation) > 0 )
		{
			axis = -axis;
		}

		Vec3 ptOnEdgeA = boxAHalfExtents;
		Vec3 ptOnEdgeB = -boxBHalfExtents;

		for (unsigned int i = 0; i < 3; i++)
		{
			if (i == axisIndexA) 
			{ 
				ptOnEdgeA[i] = 0; 
			}
			else if (boxATransform.getAxisVector(i).dot(axis) > 0) 
			{ 
				ptOnEdgeA[i] = -ptOnEdgeA[i]; 
			}

			if (i == axisIndexB) 
			{ 
				ptOnEdgeB[i] = 0;
			}
			else if (boxBTransform.getAxisVector(i).dot(axis) > 0) 
			{ 
				ptOnEdgeB[i] = -ptOnEdgeB[i]; 
			}
		}

		// Transform the points into world coordinates.
		ptOnEdgeA = boxATransform * ptOnEdgeA;
		ptOnEdgeB = boxBTransform * ptOnEdgeB;

		// Find the point of closest approach of the two
		// line-segments.
		Vec3 vertex = contactPoint(ptOnEdgeA, axisA, boxAHalfExtents.get(axisIndexA), ptOnEdgeB, axisB, boxBHalfExtents.get(axisIndexB), bestSingleAxis > 2);


		// Create contact data
		ContactPoint newContact;
		
		newContact.normal = axis;
		newContact.penetration = smallestPen;
		newContact.position = vertex;
		
		contactManifold.addContactPoint(newContact);
	}

	return;
}