Beispiel #1
0
cpVect
cpBBClampVect(const cpBB bb, const cpVect v)
{
	cpFloat x = cpfmin(cpfmax(bb.l, v.x), bb.r);
	cpFloat y = cpfmin(cpfmax(bb.b, v.y), bb.t);
	return cpv(x, y);
}
Beispiel #2
0
static cpBB
cpPolyShapeCacheData(cpShape *shape, cpVect p, cpVect rot)
{
	cpPolyShape *poly = (cpPolyShape *)shape;
	
	cpFloat l, b, r, t;
	
	cpPolyShapeTransformAxes(poly, p, rot);
	cpPolyShapeTransformVerts(poly, p, rot);
	
	cpVect *verts = poly->tVerts;
	l = r = verts[0].x;
	b = t = verts[0].y;
	
	// TODO do as part of cpPolyShapeTransformVerts?
	for(int i=1; i<poly->numVerts; i++){
		cpVect v = verts[i];
		
		l = cpfmin(l, v.x);
		r = cpfmax(r, v.x);
		
		b = cpfmin(b, v.y);
		t = cpfmax(t, v.y);
	}
	
	return cpBBNew(l, b, r, t);
}
static cpBB
cpPolyShapeCacheData(cpPolyShape *poly, cpTransform transform)
{
	int count = poly->count;
	struct cpSplittingPlane *dst = poly->planes;
	struct cpSplittingPlane *src = dst + count;
	
	cpFloat l = (cpFloat)INFINITY, r = -(cpFloat)INFINITY;
	cpFloat b = (cpFloat)INFINITY, t = -(cpFloat)INFINITY;
	
	for(int i=0; i<count; i++){
		cpVect v = cpTransformPoint(transform, src[i].v0);
		cpVect n = cpTransformVect(transform, src[i].n);
		
		dst[i].v0 = v;
		dst[i].n = n;
		
		l = cpfmin(l, v.x);
		r = cpfmax(r, v.x);
		b = cpfmin(b, v.y);
		t = cpfmax(t, v.y);
	}
	
	cpFloat radius = poly->r;
	return (poly->shape.bb = cpBBNew(l - radius, b - radius, r + radius, t + radius));
}
Beispiel #4
0
static void
applyImpulse(cpPulleyJoint *joint)
{
	cpBody* b1 = joint->constraint.a;
	cpBody* b2 = joint->constraint.b;
	cpVect r1 = joint->r1;
	cpVect r2 = joint->r2;

	// The magic and mystery below
	if (joint->state)
	{
		cpVect v1 = cpvadd(b1->v, cpv(-b1->w * r1.y, b1->w * r1.x));
		cpVect v2 = cpvadd(b2->v, cpv(-b2->w * r2.y, b2->w * r2.x));

		cpFloat Cdot = -cpvdot(joint->u1, v1) - joint->ratio * cpvdot(joint->u2, v2);
		cpFloat impulse = joint->pulleyMass * (-Cdot);
		cpFloat oldImpulse = joint->jnAcc;
		joint->jnAcc = cpfmax(0.0f, joint->jnAcc + impulse);
		impulse = joint->jnAcc - oldImpulse;

		cpVect P1 = cpvmult(joint->u1, -impulse);
		cpVect P2 = cpvmult(joint->u2, -joint->ratio * impulse);
		
		cpBodyApplyImpulse(b1, P1, r1);
		cpBodyApplyImpulse(b2, P2, r2);
	}

	if (joint->limitState1)
	{
		cpVect v1 = cpvadd(b1->v, cpv(-b1->w * r1.y, b1->w * r1.x));

		cpFloat Cdot = -cpvdot(joint->u1, v1);
		cpFloat impulse = -joint->limitMass1 * Cdot;
		cpFloat oldImpulse = joint->jnAccLim1;
		joint->jnAccLim1 = cpfmax(0.0f, joint->jnAccLim1 + impulse);
		impulse = joint->jnAccLim1 - oldImpulse;

		cpVect P1 = cpvmult(joint->u1, -impulse);

		cpBodyApplyImpulse(b1, P1, r1);
	}

	if (joint->limitState2)
	{	
		cpVect v2 = cpvadd(b2->v, cpv(-b2->w * r2.y, b2->w * r2.x));

		cpFloat Cdot = -cpvdot(joint->u2, v2);
		cpFloat impulse = -joint->limitMass2 * Cdot;
		cpFloat oldImpulse = joint->jnAccLim2;
		joint->jnAccLim2 = cpfmax(0.0f, joint->jnAccLim2 + impulse);
		impulse = joint->jnAccLim2 - oldImpulse;

		cpVect P2 = cpvmult(joint->u2, -impulse);

		cpBodyApplyImpulse(b2, P2, r2);
	}
}
void
cpArbiterApplyImpulse(cpArbiter *arb)
{
	cpBody *a = arb->a->body;
	cpBody *b = arb->b->body;

	for(int i=0; i<arb->numContacts; i++){
		cpContact *con = &arb->contacts[i];
		cpVect n = con->n;
		cpVect r1 = con->r1;
		cpVect r2 = con->r2;
		
		// Calculate the relative bias velocities.
		cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));
		cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));
		cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
		
		// Calculate and clamp the bias impulse.
		cpFloat jbn = (con->bias - vbn)*con->nMass;
		cpFloat jbnOld = con->jBias;
		con->jBias = cpfmax(jbnOld + jbn, 0.0f);
		jbn = con->jBias - jbnOld;
		
		// Apply the bias impulse.
		cpVect jb = cpvmult(n, jbn);
		cpBodyApplyBiasImpulse(a, cpvneg(jb), r1);
		cpBodyApplyBiasImpulse(b, jb, r2);

		// Calculate the relative velocity.
		cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));
		cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));
		cpVect vr = cpvsub(v2, v1);
		cpFloat vrn = cpvdot(vr, n);
		
		// Calculate and clamp the normal impulse.
		cpFloat jn = -(con->bounce + vrn)*con->nMass;
		cpFloat jnOld = con->jnAcc;
		con->jnAcc = cpfmax(jnOld + jn, 0.0f);
		jn = con->jnAcc - jnOld;
		
		// Calculate the relative tangent velocity.
		cpVect t = cpvperp(n);
		cpFloat vrt = cpvdot(cpvadd(vr, arb->target_v), t);
		
		// Calculate and clamp the friction impulse.
		cpFloat jtMax = arb->u*con->jnAcc;
		cpFloat jt = -vrt*con->tMass;
		cpFloat jtOld = con->jtAcc;
		con->jtAcc = cpfmin(cpfmax(jtOld + jt, -jtMax), jtMax);
		jt = con->jtAcc - jtOld;
		
		// Apply the final impulse.
		cpVect j = cpvadd(cpvmult(n, jn), cpvmult(t, jt));
		cpBodyApplyImpulse(a, cpvneg(j), r1);
		cpBodyApplyImpulse(b, j, r2);
	}
}
Beispiel #6
0
void
cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef)
{
	cpBody *a = arb->a->body;
	cpBody *b = arb->b->body;

	for(int i=0; i<arb->numContacts; i++){
		cpContact *con = &arb->contacts[i];
		cpVect n = con->n;
		cpVect r1 = con->r1;
		cpVect r2 = con->r2;
		
		// Calculate the relative bias velocities.
		cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));
		cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));
		cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
		
		// Calculate and clamp the bias impulse.
		cpFloat jbn = (con->bias - vbn)*con->nMass;
		cpFloat jbnOld = con->jBias;
		con->jBias = cpfmax(jbnOld + jbn, 0.0f);
		jbn = con->jBias - jbnOld;
		
		// Apply the bias impulse.
		apply_bias_impulses(a, b, r1, r2, cpvmult(n, jbn));

		// Calculate the relative velocity.
		cpVect vr = relative_velocity(a, b, r1, r2);
		cpFloat vrn = cpvdot(vr, n);
		
		// Calculate and clamp the normal impulse.
		cpFloat jn = -(con->bounce*eCoef + vrn)*con->nMass;
		cpFloat jnOld = con->jnAcc;
		con->jnAcc = cpfmax(jnOld + jn, 0.0f);
		jn = con->jnAcc - jnOld;
		
		// Calculate the relative tangent velocity.
		cpFloat vrt = cpvdot(cpvadd(vr, arb->surface_vr), cpvperp(n));
		
		// Calculate and clamp the friction impulse.
		cpFloat jtMax = arb->u*con->jnAcc;
		cpFloat jt = -vrt*con->tMass;
		cpFloat jtOld = con->jtAcc;
		con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);
		jt = con->jtAcc - jtOld;
		
		// Apply the final impulse.
		apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(jn, jt)));
	}
}
Beispiel #7
0
static void
NodeRender(Node *node, int depth)
{
	if(!NodeIsLeaf(node) && depth <= 10){
		NodeRender(node->a, depth + 1);
		NodeRender(node->b, depth + 1);
	}
	
	cpBB bb = node->bb;
	
//	GLfloat v = depth/2.0f;	
//	glColor3f(1.0f - v, v, 0.0f);
	glLineWidth(cpfmax(5.0f - depth, 1.0f));
	glBegin(GL_LINES); {
		glVertex2f(bb.l, bb.b);
		glVertex2f(bb.l, bb.t);
		
		glVertex2f(bb.l, bb.t);
		glVertex2f(bb.r, bb.t);
		
		glVertex2f(bb.r, bb.t);
		glVertex2f(bb.r, bb.b);
		
		glVertex2f(bb.r, bb.b);
		glVertex2f(bb.l, bb.b);
	}; glEnd();
}
Beispiel #8
0
static void
playerUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{
	cpBodyUpdateVelocity(body, gravity, damping, dt);
	body->v.y = cpfmax(body->v.y, -700);
	body->v.x = cpfclamp(body->v.x, -400, 400);
}
void
cpSpaceNearestPointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpLayers layers, cpGroup group, cpSpaceNearestPointQueryFunc func, void *data)
{
	struct NearestPointQueryContext context = {point, maxDistance, layers, group, func};
	cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f));
	
	cpSpaceLock(space); {
		cpSpatialIndexQuery(space->activeShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data);
		cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data);
	} cpSpaceUnlock(space, cpTrue);
}
Beispiel #10
0
static cpBB
cpPolyShapeTransformVerts(cpPolyShape *poly, cpVect p, cpVect rot)
{
    cpVect *src = poly->verts;
    cpVect *dst = poly->tVerts;

    cpFloat l = (cpFloat)INFINITY, r = -(cpFloat)INFINITY;
    cpFloat b = (cpFloat)INFINITY, t = -(cpFloat)INFINITY;

    for(int i=0; i<poly->numVerts; i++) {
        cpVect v = cpvadd(p, cpvrotate(src[i], rot));

        dst[i] = v;
        l = cpfmin(l, v.x);
        r = cpfmax(r, v.x);
        b = cpfmin(b, v.y);
        t = cpfmax(t, v.y);
    }

    return cpBBNew(l, b, r, t);
}
Beispiel #11
0
void
cpArbiterApplyImpulse(cpArbiter *arb)
{
	cpBody *a = arb->body_a;
	cpBody *b = arb->body_b;
	cpVect surface_vr = arb->surface_vr;
	cpFloat friction = arb->u;

	for(int i=0; i<arb->numContacts; i++){
		cpContact *con = &arb->contacts[i];
		cpFloat nMass = con->nMass;
		cpVect n = con->n;
		cpVect r1 = con->r1;
		cpVect r2 = con->r2;

		cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));
		cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));
		cpVect vr = relative_velocity(a, b, r1, r2);

		cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
		cpFloat vrn = cpvdot(vr, n);
		cpFloat vrt = cpvdot(cpvadd(vr, surface_vr), cpvperp(n));

		cpFloat jbn = (con->bias - vbn)*nMass;
		cpFloat jbnOld = con->jBias;
		con->jBias = cpfmax(jbnOld + jbn, 0.0f);

		cpFloat jn = -(con->bounce + vrn)*nMass;
		cpFloat jnOld = con->jnAcc;
		con->jnAcc = cpfmax(jnOld + jn, 0.0f);

		cpFloat jtMax = friction*con->jnAcc;
		cpFloat jt = -vrt*con->tMass;
		cpFloat jtOld = con->jtAcc;
		con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);

		apply_bias_impulses(a, b, r1, r2, cpvmult(n, con->jBias - jbnOld));
		apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(con->jnAcc - jnOld, con->jtAcc - jtOld)));
	}
}
static void DrawShape(cpShape *shape, DrawNode *renderer)
{
    cpBody *body = cpShapeGetBody(shape);
    Color4F color = ColorForBody(body);
    
    switch (shape->CP_PRIVATE(klass)->type)
    {
        case CP_CIRCLE_SHAPE:
        {
            cpCircleShape *circle = (cpCircleShape *)shape;
            cpVect center = circle->tc;
            cpFloat radius = circle->r;
            renderer->drawDot(cpVert2Point(center), cpfmax(radius, 1.0), color);
            renderer->drawSegment(cpVert2Point(center), cpVert2Point(cpvadd(center, cpvmult(cpBodyGetRotation(body), radius))), 1.0, color);
        }
             break;
        case CP_SEGMENT_SHAPE:
        {
            cpSegmentShape *seg = (cpSegmentShape *)shape;
            renderer->drawSegment(cpVert2Point(seg->ta), cpVert2Point(seg->tb), cpfmax(seg->r, 2.0), color);
        }
            break;
        case CP_POLY_SHAPE:
        {
            cpPolyShape* poly = (cpPolyShape*)shape;
            Color4F line = color;
            line.a = cpflerp(color.a, 1.0, 0.5);
            int num = poly->count;
            Vec2* pPoints = new (std::nothrow) Vec2[num];
            for(int i=0;i<num;++i)
                pPoints[i] = cpVert2Point(poly->planes[i].v0);
            renderer->drawPolygon(pPoints, num, color, 1.0, line);
            CC_SAFE_DELETE_ARRAY(pPoints);
        }
            break;
        default:
            cpAssertHard(false, "Bad assertion in DrawShape()");
    }
}
Beispiel #13
0
// Recursive implementatino of the GJK loop.
static inline struct ClosestPoints
GJKRecurse(const struct SupportContext *ctx, const struct MinkowskiPoint v0, const struct MinkowskiPoint v1, const int iteration)
{
    if(iteration > MAX_GJK_ITERATIONS) {
        cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
        return ClosestPointsNew(v0, v1);
    }

    cpVect delta = cpvsub(v1.ab, v0.ab);
    // TODO: should this be an area2x check?
    if(cpvcross(delta, cpvadd(v0.ab, v1.ab)) > 0.0f) {
        // Origin is behind axis. Flip and try again.
        return GJKRecurse(ctx, v1, v0, iteration);
    } else {
        cpFloat t = ClosestT(v0.ab, v1.ab);
        cpVect n = (-1.0f < t && t < 1.0f ? cpvperp(delta) : cpvneg(LerpT(v0.ab, v1.ab, t)));
        struct MinkowskiPoint p = Support(ctx, n);

#if DRAW_GJK
        ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 1, 1, 1));
        cpVect c = cpvlerp(v0.ab, v1.ab, 0.5);
        ChipmunkDebugDrawSegment(c, cpvadd(c, cpvmult(cpvnormalize(n), 5.0)), RGBAColor(1, 0, 0, 1));

        ChipmunkDebugDrawDot(5.0, p.ab, LAColor(1, 1));
#endif

        if(
            cpvcross(cpvsub(v1.ab, p.ab), cpvadd(v1.ab, p.ab)) > 0.0f &&
            cpvcross(cpvsub(v0.ab, p.ab), cpvadd(v0.ab, p.ab)) < 0.0f
        ) {
            // The triangle v0, p, v1 contains the origin. Use EPA to find the MSA.
            cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK->EPA iterations: %d", iteration);
            return EPA(ctx, v0, p, v1);
        } else {
            if(cpvdot(p.ab, n) <= cpfmax(cpvdot(v0.ab, n), cpvdot(v1.ab, n))) {
                // The edge v0, v1 that we already have is the closest to (0, 0) since p was not closer.
                cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
                return ClosestPointsNew(v0, v1);
            } else {
                // p was closer to the origin than our existing edge.
                // Need to figure out which existing point to drop.
                if(ClosestDist(v0.ab, p.ab) < ClosestDist(p.ab, v1.ab)) {
                    return GJKRecurse(ctx, v0, p, iteration + 1);
                } else {
                    return GJKRecurse(ctx, p, v1, iteration + 1);
                }
            }
        }
    }
}
static void DrawShape(cpShape *shape, DrawNode *renderer)
{
    cpBody *body = shape->body;
    Color4F color = ColorForBody(body);

    switch (shape->CP_PRIVATE(klass)->type)
    {
    case CP_CIRCLE_SHAPE:
    {
        cpCircleShape *circle = (cpCircleShape *)shape;
        cpVect center = circle->tc;
        cpFloat radius = circle->r;
        renderer->drawDot(cpVert2Point(center), cpfmax(radius, 1.0), color);
        renderer->drawSegment(cpVert2Point(center), cpVert2Point(cpvadd(center, cpvmult(body->rot, radius))), 1.0, color);
    }
    break;
    case CP_SEGMENT_SHAPE:
    {
        cpSegmentShape *seg = (cpSegmentShape *)shape;
        renderer->drawSegment(cpVert2Point(seg->ta), cpVert2Point(seg->tb), cpfmax(seg->r, 2.0), color);
    }
    break;
    case CP_POLY_SHAPE:
    {
        cpPolyShape *poly = (cpPolyShape *)shape;
        Color4F line = color;
        line.a = cpflerp(color.a, 1.0, 0.5);
        Vec2* pPoints = cpVertArray2ccpArrayN(poly->tVerts, poly->numVerts);
        renderer->drawPolygon(pPoints, poly->numVerts, color, 1.0, line);
        CC_SAFE_DELETE_ARRAY(pPoints);
    }
    break;
    default:
        cpAssertHard(false, "Bad assertion in DrawShape()");
    }
}
static inline struct ClosestPoints
GJKRecurse(const struct SupportContext *ctx, const struct MinkowskiPoint v0, const struct MinkowskiPoint v1, const int iteration)
{
	if(iteration > MAX_GJK_ITERATIONS){
		cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
		return ClosestPointsNew(v0, v1);
	}
	
	cpVect delta = cpvsub(v1.ab, v0.ab);
	if(cpvcross(delta, cpvadd(v0.ab, v1.ab)) > 0.0f){
		// Origin is behind axis. Flip and try again.
		return GJKRecurse(ctx, v1, v0, iteration + 1);
	} else {
		cpFloat t = ClosestT(v0.ab, v1.ab);
		cpVect n = (-1.0f < t && t < 1.0f ? cpvperp(delta) : cpvneg(LerpT(v0.ab, v1.ab, t)));
		struct MinkowskiPoint p = Support(ctx, n);
		
#if DRAW_GJK
		ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 1, 1, 1));
		cpVect c = cpvlerp(v0.ab, v1.ab, 0.5);
		ChipmunkDebugDrawSegment(c, cpvadd(c, cpvmult(cpvnormalize(n), 5.0)), RGBAColor(1, 0, 0, 1));
		
		ChipmunkDebugDrawDot(5.0, p.ab, LAColor(1, 1));
#endif
		
		if(
			cpvcross(cpvsub(v1.ab, p.ab), cpvadd(v1.ab, p.ab)) > 0.0f &&
			cpvcross(cpvsub(v0.ab, p.ab), cpvadd(v0.ab, p.ab)) < 0.0f
		){
			cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK->EPA iterations: %d", iteration);
			// The triangle v0, p, v1 contains the origin. Use EPA to find the MSA.
			return EPA(ctx, v0, p, v1);
		} else {
			// The new point must be farther along the normal than the existing points.
			if(cpvdot(p.ab, n) <= cpfmax(cpvdot(v0.ab, n), cpvdot(v1.ab, n))){
				cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
				return ClosestPointsNew(v0, v1);
			} else {
				if(ClosestDist(v0.ab, p.ab) < ClosestDist(p.ab, v1.ab)){
					return GJKRecurse(ctx, v0, p, iteration + 1);
				} else {
					return GJKRecurse(ctx, p, v1, iteration + 1);
				}
			}
		}
	}
}
static void
update(cpSpace *space, double dt)
{
	// Set the first anchor point (the one attached to the static body) of the dolly servo to the mouse's x position.
	cpPivotJointSetAnchorA(dollyServo, cpv(ChipmunkDemoMouse.x, 100));
	
	// Set the max length of the winch servo to match the mouse's height.
	cpSlideJointSetMax(winchServo, cpfmax(100 - ChipmunkDemoMouse.y, 50));
	
	if(hookJoint && ChipmunkDemoRightClick){
		cpSpaceRemoveConstraint(space, hookJoint);
		cpConstraintFree(hookJoint);
		hookJoint = NULL;
	}
	
	cpSpaceStep(space, dt);
}
Beispiel #17
0
static inline cpBB
GetBB(cpBBTree *tree, void *obj)
{
	cpBB bb = tree->spatialIndex.bbfunc(obj);
	
	cpBBTreeVelocityFunc velocityFunc = tree->velocityFunc;
	if(velocityFunc){
		cpFloat coef = 0.1f;
		cpFloat x = (bb.r - bb.l)*coef;
		cpFloat y = (bb.t - bb.b)*coef;
		
		cpVect v = cpvmult(velocityFunc(obj), 0.1f);
		return cpBBNew(bb.l + cpfmin(-x, v.x), bb.b + cpfmin(-y, v.y), bb.r + cpfmax(x, v.x), bb.t + cpfmax(y, v.y));
	} else {
		return bb;
	}
}
Beispiel #18
0
static void
update(int ticks)
{
	if(arrowDirection.y){
		circleRadius = cpfmax(10.0f, circleRadius + arrowDirection.y);
		
		for(int i=0; i<NUM_CIRCLES; i++){
			circles[i]->body->m = cpMomentForCircle(1.0f, 0.0f, circleRadius, cpvzero);
			cpCircleShapeSetRadius(circles[i], circleRadius);
		}
	}
	
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;
	
	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}
Beispiel #19
0
static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;
	
	for(int i=0; i<steps; i++){
		// Set the first anchor point (the one attached to the static body) of the dolly servo to the mouse's x position.
		cpPivotJointSetAnchr1(dollyServo, cpv(ChipmunkDemoMouse.x, 100));
		
		// Set the max length of the winch servo to match the mouse's height.
		cpSlideJointSetMax(winchServo, cpfmax(100 - ChipmunkDemoMouse.y, 50));
		
		if(hookJoint && ChipmunkDemoKeyboard.y < 0){
			cpSpaceRemoveConstraint(space, hookJoint);
			cpConstraintFree(hookJoint);
			hookJoint = NULL;
		}
		
		cpSpaceStep(space, dt);
	}
}
cpShape *
cpSpaceNearestPointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpLayers layers, cpGroup group, cpNearestPointQueryInfo *out)
{
	cpNearestPointQueryInfo info = {NULL, cpvzero, maxDistance, cpvzero};
	if(out){
		(*out) = info;
  } else {
		out = &info;
	}
	
	struct NearestPointQueryContext context = {
		point, maxDistance,
		layers, group,
		NULL
	};
	
	cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f));
	cpSpatialIndexQuery(space->activeShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out);
	cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out);
	
	return out->shape;
}
Beispiel #21
0
cpBool
cpCheckAxis(cpVect v0, cpVect v1, cpVect p, cpVect n){
	return cpvdot(p, n) <= cpfmax(cpvdot(v0, n), cpvdot(v1, n));
}