Example #1
0
cpPolyline *
cpPolylineToConvexHull(cpPolyline *line, cpFloat tol)
{
	cpPolyline *hull = cpPolylineMake(line->count + 1);
	hull->count = cpConvexHull(line->count, line->verts, hull->verts, NULL, tol);
	hull = cpPolylinePush(hull, hull->verts[0]);
	
	return cpPolylineShrink(hull);
}
Example #2
0
// Find the closest points between two shapes using the GJK algorithm.
static struct ClosestPoints
GJK(const struct SupportContext *ctx, cpCollisionID *id)
{
#if DRAW_GJK || DRAW_EPA
    int count1 = 1;
    int count2 = 1;

    switch(ctx->shape1->klass->type) {
    case CP_SEGMENT_SHAPE:
        count1 = 2;
        break;
    case CP_POLY_SHAPE:
        count1 = ((cpPolyShape *)ctx->shape1)->count;
        break;
    default:
        break;
    }

    switch(ctx->shape2->klass->type) {
    case CP_SEGMENT_SHAPE:
        count1 = 2;
        break;
    case CP_POLY_SHAPE:
        count2 = ((cpPolyShape *)ctx->shape2)->count;
        break;
    default:
        break;
    }


    // draw the minkowski difference origin
    cpVect origin = cpvzero;
    ChipmunkDebugDrawDot(5.0, origin, RGBAColor(1,0,0,1));

    int mdiffCount = count1*count2;
    cpVect *mdiffVerts = alloca(mdiffCount*sizeof(cpVect));

    for(int i=0; i<count1; i++) {
        for(int j=0; j<count2; j++) {
            cpVect v = cpvsub(ShapePoint(ctx->shape2, j).p, ShapePoint(ctx->shape1, i).p);
            mdiffVerts[i*count2 + j] = v;
            ChipmunkDebugDrawDot(2.0, v, RGBAColor(1, 0, 0, 1));
        }
    }

    cpVect *hullVerts = alloca(mdiffCount*sizeof(cpVect));
    int hullCount = cpConvexHull(mdiffCount, mdiffVerts, hullVerts, NULL, 0.0);

    ChipmunkDebugDrawPolygon(hullCount, hullVerts, 0.0, RGBAColor(1, 0, 0, 1), RGBAColor(1, 0, 0, 0.25));
#endif

    struct MinkowskiPoint v0, v1;
    if(*id) {
        // Use the minkowski points from the last frame as a starting point using the cached indexes.
        v0 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>>24)&0xFF), ShapePoint(ctx->shape2, (*id>>16)&0xFF));
        v1 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>> 8)&0xFF), ShapePoint(ctx->shape2, (*id    )&0xFF));
    } else {
void
cpPolyShapeSetVerts(cpShape *shape, int count, cpVect *verts, cpTransform transform)
{
	cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect));
	
	// Transform the verts before building the hull in case of a negative scale.
	for(int i=0; i<count; i++) hullVerts[i] = cpTransformPoint(transform, verts[i]);
	
	unsigned int hullCount = cpConvexHull(count, hullVerts, hullVerts, NULL, 0.0);
	cpPolyShapeSetVertsRaw(shape, hullCount, hullVerts);
}
cpPolyShape *
cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius)
{
	cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect));
	
	// Transform the verts before building the hull in case of a negative scale.
	for(int i=0; i<count; i++) hullVerts[i] = cpTransformPoint(transform, verts[i]);
	
	unsigned int hullCount = cpConvexHull(count, hullVerts, hullVerts, NULL, 0.0);
	return cpPolyShapeInitRaw(poly, body, hullCount, hullVerts, radius);
}
Example #5
0
unsigned int physics_convex_hull(unsigned int nverts, Vec2 *verts)
{
    cpVect *cpverts;
    unsigned int i;

    cpverts = malloc(nverts * sizeof(cpVect));
    for (i = 0; i < nverts; ++i)
        cpverts[i] = cpv_of_vec2(verts[i]);
    nverts = cpConvexHull(nverts, cpverts, NULL, NULL, 0);
    for (i = 0; i < nverts; ++i)
        verts[i] = vec2_of_cpv(cpverts[i]);
    free(cpverts);
    return nverts;
}
Example #6
0
unsigned int physics_shape_add_poly(Entity ent,
                                    unsigned int nverts,
                                    const Vec2 *verts,
                                    Scalar r)
{
    unsigned int i;
    cpVect *cpverts;
    cpShape *shape;

    cpverts = malloc(nverts * sizeof(cpVect));
    for (i = 0; i < nverts; ++i)
        cpverts[i] = cpv_of_vec2(verts[i]);
    nverts = cpConvexHull(nverts, cpverts, NULL, NULL, 0);
    shape = cpPolyShapeNew2(NULL, nverts, cpverts, cpvzero, r);
    free(cpverts);
    return _shape_add(ent, PS_POLYGON, shape);
}
Example #7
0
static void
update(cpSpace *space)
{
	cpFloat tolerance = 2.0;
	
	if(ChipmunkDemoRightClick && cpShapeNearestPointQuery(shape, ChipmunkDemoMouse, NULL) > tolerance){
		cpBody *body = cpShapeGetBody(shape);
		int count = cpPolyShapeGetNumVerts(shape);
		
		// Allocate the space for the new vertexes on the stack.
		cpVect *verts = (cpVect *)alloca((count + 1)*sizeof(cpVect));
		
		for(int i=0; i<count; i++){
			verts[i] = cpPolyShapeGetVert(shape, i);
		}
		
		verts[count] = cpBodyWorld2Local(body, ChipmunkDemoMouse);
		
		// This function builds a convex hull for the vertexes.
		// Because the result array is NULL, it will reduce the input array instead.
		int hullCount = cpConvexHull(count + 1, verts, NULL, NULL, tolerance);
		
		// Figure out how much to shift the body by.
		cpVect centroid = cpCentroidForPoly(hullCount, verts);
		
		// Recalculate the body properties to match the updated shape.
		cpFloat mass = cpAreaForPoly(hullCount, verts)*DENSITY;
		cpBodySetMass(body, mass);
		cpBodySetMoment(body, cpMomentForPoly(mass, hullCount, verts, cpvneg(centroid)));
		cpBodySetPos(body, cpBodyLocal2World(body, centroid));
		
		// Use the setter function from chipmunk_unsafe.h.
		// You could also remove and recreate the shape if you wanted.
		cpPolyShapeSetVerts(shape, hullCount, verts, cpvneg(centroid));
	}
	
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;
	
	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}
Example #8
0
static void
ApproximateConcaveDecomposition(cpVect *verts, int count, cpFloat tol, cpPolylineSet *set)
{
	int first;
	cpVect *hullVerts = alloca(count*sizeof(cpVect));
	int hullCount = cpConvexHull(count, verts, hullVerts, &first, 0.0);
	
	if(hullCount != count){
		struct Notch notch = DeepestNotch(count, verts, hullCount, hullVerts, first, tol);
		
		if(notch.d > tol){
			cpFloat steiner_it = FindSteiner(count, verts, notch);
			
			if(steiner_it >= 0.0){
				int steiner_i = (int)steiner_it;
				cpVect steiner = cpvlerp(verts[steiner_i], verts[Next(steiner_i, count)], steiner_it - steiner_i);
				
				// Vertex counts NOT including the steiner point.
				int sub1_count = (steiner_i - notch.i + count)%count + 1;
				int sub2_count = count - (steiner_i - notch.i + count)%count;
				cpVect *scratch = alloca((IMAX(sub1_count, sub2_count) + 1)*sizeof(cpVect));
				
				for(int i=0; i<sub1_count; i++) scratch[i] = verts[(notch.i + i)%count];
				scratch[sub1_count] = steiner;
				ApproximateConcaveDecomposition(scratch, sub1_count + 1, tol, set);
				
				for(int i=0; i<sub2_count; i++) scratch[i] = verts[(steiner_i + 1 + i)%count];
				scratch[sub2_count] = steiner;
				ApproximateConcaveDecomposition(scratch, sub2_count + 1, tol, set);
				
				return;
			}
		}
	}
	
	cpPolyline *hull = cpPolylineMake(hullCount + 1);
	
	memcpy(hull->verts, hullVerts, hullCount*sizeof(cpVect));
	hull->verts[hullCount] = hullVerts[0];
	hull->count = hullCount + 1;
	
	cpPolylineSetPush(set, hull);
}
void ColliderDetector::updateTransform(AffineTransform &t)
{
    if (!m_bActive)
    {
        return;
    }

    for(auto object : *m_pColliderBodyList)
    {
        ColliderBody *colliderBody = (ColliderBody *)object;
        ContourData *contourData = colliderBody->getContourData();

        b2PolygonShape* b2shape = nullptr;
        if (m_pB2Body != nullptr)
        {
            b2shape = (b2PolygonShape *)colliderBody->getB2Fixture()->GetShape();
        }

        cpPolyShape* cpshape = nullptr;
        if (m_pCPBody != nullptr)
        {
            cpshape = (cpPolyShape *)colliderBody->getShape();
        }

        int num = contourData->m_tVertexList.count();
        ContourVertex2 **vs = (ContourVertex2 **)contourData->m_tVertexList.data->arr;

#if ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX
        ContourVertex2 **cvs = (ContourVertex2 **)colliderBody->getCalculatedVertexList()->data->arr;
#endif

        for (int i = 0; i < num; i++)
        {
            helpPoint.setPoint( vs[i]->x,  vs[i]->y);
            helpPoint = PointApplyAffineTransform(helpPoint, t);


#if ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX
            cvs[i]->x = helpPoint.x;
            cvs[i]->y = helpPoint.y;
#endif

            if ( b2shape != nullptr )
            {
                b2Vec2 &bv = b2shape->m_vertices[i];
                bv.Set(helpPoint.x / PT_RATIO, helpPoint.y / PT_RATIO);
            }

            if ( cpshape != nullptr )
            {
                cpVect v ;
                v.x = helpPoint.x;
                v.y = helpPoint.y;
                cpshape->verts[i] = v;
            }
        }

		if ( cpshape != nullptr )
		{
			cpConvexHull(num, cpshape->verts, nullptr, nullptr, 0);
			for (int i = 0; i < num; i++)
			{
				cpVect b = cpshape->verts[(i + 1) % cpshape->numVerts];
				cpVect n = cpvnormalize(cpvperp(cpvsub(b, cpshape->verts[i])));

				cpshape->planes[i].n = n;
				cpshape->planes[i].d = cpvdot(n, cpshape->verts[i]);
			}
		}
    }
}
Example #10
0
void ColliderDetector::updateTransform(Mat4 &t)
{
    if (!_active)
    {
        return;
    }

    for(auto& object : _colliderBodyList)
    {
        ColliderBody *colliderBody = (ColliderBody *)object;
        ContourData *contourData = colliderBody->getContourData();

#if ENABLE_PHYSICS_BOX2D_DETECT
        b2PolygonShape *shape = nullptr;
        if (_body != nullptr)
        {
            shape = (b2PolygonShape *)colliderBody->getB2Fixture()->GetShape();
        }
#elif ENABLE_PHYSICS_CHIPMUNK_DETECT
        cpPolyShape *shape = nullptr;
        if (_body != nullptr)
        {
            shape = (cpPolyShape *)colliderBody->getShape();
        }
#endif

        unsigned long num = contourData->vertexList.size();
        std::vector<cocos2d::Vec2> &vs = contourData->vertexList;

#if ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX
        std::vector<cocos2d::Vec2> &cvs = colliderBody->_calculatedVertexList;
#endif

        for (unsigned long i = 0; i < num; i++)
        {
            helpPoint.setPoint( vs.at(i).x,  vs.at(i).y);
            helpPoint = PointApplyTransform(helpPoint, t);


#if ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX
            cvs.at(i).x = helpPoint.x;
            cvs.at(i).y = helpPoint.y;
#endif

#if ENABLE_PHYSICS_BOX2D_DETECT
            if (shape != nullptr)
            {
                b2Vec2 &bv = shape->m_vertices[i];
                bv.Set(helpPoint.x / PT_RATIO, helpPoint.y / PT_RATIO);
            }
#elif ENABLE_PHYSICS_CHIPMUNK_DETECT
            if (shape != nullptr)
            {
                cpVect v ;
                v.x = helpPoint.x;
                v.y = helpPoint.y;
                shape->verts[i] = v;
            }
#endif
        }

#if ENABLE_PHYSICS_CHIPMUNK_DETECT
        cpConvexHull((int)num, shape->verts, nullptr, nullptr, 0);
        for (unsigned long i = 0; i < num; i++)
        {
            cpVect b = shape->verts[(i + 1) % shape->numVerts];
            cpVect n = cpvnormalize(cpvperp(cpvsub(b, shape->verts[i])));

            shape->planes[i].n = n;
            shape->planes[i].d = cpvdot(n, shape->verts[i]);
        }
#endif
    }
}