//Handles checking of collision with mouse and geometry and applying force on collision
void TestApplication::checkMouseCollision() {
    for (size_t i = 0; i < _circleBodies.size(); ++i) {
        CircleBody& body = *_circleBodies[i];
        
        //Check if mouse collides
        if (_leftMouseDown) {
            Vector2f mouse = (_previousMousePosition + _camera.position()) * 0.01f; //Scale mouse position to world coordinates
            
            Vector2f d = mouse - body.position();
            
            if (d.lengthSquared() < body.radius() * body.radius())
                body.applyForce(_mouseForce);
        }
    }
    
    for (size_t i = 0; i < _polygonBodies.size(); ++i) {
        PolygonBody& body = *_polygonBodies[i];
        const std::vector<Vector2f>& verts = body.verticesWorldSpace();
        
        //Check if the polygon and mouse collide
        if (_leftMouseDown) {
            Vector2f mouse = (_previousMousePosition + _camera.position()) * 0.01f; //Scale mouse position to world coordinates
            
            Vector2f d = mouse - body.position();
            
            if (d.lengthSquared() < body.radius() * body.radius()) {
                bool collides = false;
                
                for (int j = 0, k = verts.size() - 1; j < verts.size(); k = j++) {
                    if ( ((verts[j].y > mouse.y) != (verts[k].y > mouse.y)) && (mouse.x < (verts[k].x - verts[j].x) * (mouse.y - verts[j].y) / (verts[k].y - verts[j].y) + verts[j].x))
                        collides = !collides;
                }
                
                if (collides)
                    body.applyForce(_mouseForce);
            }
        }
    }
}
示例#2
0
	void Polygon2f::DoShrink(float distance, list<Polygon2f*> &parentPolygons, list<Polygon2f*> &polygons)
	{
		float distance2 = sqr(distance);
		list<Line2f> resLines;

		size_t count = vertices.size();

		// build list with point translations
		for(int i=0; i<count;i++)
		{
			Line2f l;
			Vector2f Na = vertices[(i-1+count)%count];
			Vector2f Nb = vertices[i];
			Vector2f Nc = vertices[(i+1)%count];
			l.src = Nb;

			Vector2f V1 = (Nb-Na).getNormalized();
			Vector2f V2 = (Nc-Nb).getNormalized();

			Vector2f biplane = (V2 - V1).getNormalized();
			if( biplane.lengthSquared() == 0 )
			{
				biplane.x = V1.y;
				biplane.y = -V1.x;
			}
			
			float a = CalcAngleBetween(V1,V2);

			bool convex = V1.cross(V2) < 0;
			Vector2f p;

			if(convex)
			{
				p = Nb+biplane*distance/(cos((PI-a)*0.5f));
				l.vertices.push_back(p);
			}
			else
			{
				if( a < PI*1.25 )
				{
					p = Nb-biplane*distance/(sin(a*0.5f));
					l.vertices.push_back(p);
				}
				else
				{
					p = Nb+Vector2f(V1.y, -V1.x)*distance;
					l.vertices.push_back(p);

					p = Nb-biplane*distance;
					l.vertices.push_back(p);

					p = Nb+Vector2f(V2.y, -V2.x)*distance;
					l.vertices.push_back(p);
				}
			}
			resLines.push_back(l);
		}

		Line2f::CleanOutLine(resLines, distance2);
		vector<Vector2f> resVectors;

		for(list<Line2f>::iterator lIt = resLines.begin(); lIt != resLines.end(); lIt++)
		{
			for(list<Vector2f>::iterator pIt = lIt->vertices.begin(); pIt != lIt->vertices.end(); pIt++ )
			{
				resVectors.push_back(*pIt);
			}
		}

		DoAddPolygonOutline(distance, resVectors, parentPolygons, polygons);
	}
示例#3
0
//We use a modified Separating Axis Test to test for polygon-circle collisions
bool PolygonBody::checkCollision(CircleBody& circle, Collision& collision) {
    float radiusSum = _radius + circle.radius();
    
    if ((circle.position() - _position).lengthSquared() > radiusSum * radiusSum)
        return false;
    
    std::vector<Vector2f> axes;
    this->calculateNormals(axes);
    
    //We need the axis from the center of the circle to the closest vertex on the polygon
    Vector2f additionalAxis = _verticesWorldSpace[0] - circle.position();
    
    for (size_t i = 1; i < _verticesWorldSpace.size(); ++i) {
        Vector2f v = _verticesWorldSpace[i] - circle.position();
        
        if (v.lengthSquared() < additionalAxis.lengthSquared())
            additionalAxis = v;
    }
    
    additionalAxis.normalize();
    axes.push_back(additionalAxis);
    
    float minOverlap = std::numeric_limits<float>::max();
    Vector2f minOverlapAxis;
    
    for (size_t i = 0; i < axes.size(); ++i) {
        Vector2f& axis = axes[i];
        
        float projection = axis.dotProduct(_verticesWorldSpace.front());
        float aMinProjection = projection;
        float aMaxProjection = projection;
        
        for (size_t j = 1; j < _verticesWorldSpace.size(); ++j) {
            projection = axis.dotProduct(_verticesWorldSpace[j]);
            
            aMinProjection = std::min(aMinProjection, projection);
            aMaxProjection = std::max(aMaxProjection, projection);
        }
        
        projection = axis.dotProduct(circle.position());
        float bMinProjection = projection - circle.radius();
        float bMaxProjection = projection + circle.radius();
        
        if (bMinProjection > bMaxProjection)
            std::swap(bMinProjection, bMaxProjection);
        
        if ((aMaxProjection < bMinProjection) || (bMaxProjection < aMinProjection))
            return false; //This axis has no overlap, a collision is not possible
        
        float lowerOverlap = aMaxProjection - bMinProjection;
        float upperOverlap = bMaxProjection - aMinProjection;
        
        if (lowerOverlap < minOverlap) {
            minOverlap = lowerOverlap;
            minOverlapAxis = axis;
        }
        
        if (upperOverlap < minOverlap) {
            minOverlap = upperOverlap;
            minOverlapAxis = -axis;
        }
    }

    collision.bodyA = this;
    collision.bodyB = &circle;
    collision.normal = minOverlapAxis;
    collision.depth = minOverlap;
    collision.contactPoints.push_back(circle.position() - collision.normal * (circle.radius() - collision.depth));

    return true;
}