Пример #1
0
static void
setUpVerts(cpPolyShape *poly, int numVerts, cpVect *verts, cpVect offset)
{
	// Fail if the user attempts to pass a concave poly, or a bad winding.
	cpAssertHard(cpPolyValidate(verts, numVerts), "Polygon is concave or has a reversed winding. Consider using cpConvexHull() or CP_CONVEX_HULL().");
	
	poly->numVerts = numVerts;
	poly->verts = (cpVect *)cpcalloc(2*numVerts, sizeof(cpVect));
	poly->planes = (cpSplittingPlane *)cpcalloc(2*numVerts, sizeof(cpSplittingPlane));
	poly->tVerts = poly->verts + numVerts;
	poly->tPlanes = poly->planes + numVerts;
	
	for(int i=0; i<numVerts; i++){
		cpVect a = cpvadd(offset, verts[i]);
		cpVect b = cpvadd(offset, verts[(i+1)%numVerts]);
		cpVect n = cpvnormalize(cpvperp(cpvsub(b, a)));

		poly->verts[i] = a;
		poly->planes[i].n = n;
		poly->planes[i].d = cpvdot(n, a);
	}
	
}
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]);
			}
		}
    }
}
Пример #3
0
cpVect * bmx_cpvect_normalize(cpVect * vec) {
	return bmx_cpvect_new(cpvnormalize(*vec));
}
Пример #4
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
    }
}
Пример #5
0
static inline cpFloat
Sharpness(cpVect a, cpVect b, cpVect c)
{
	// TODO could speed this up by caching the normals instead of calculating each twice.
  return cpvdot(cpvnormalize(cpvsub(a, b)), cpvnormalize(cpvsub(c, b)));
}
Пример #6
0
static void update(void) {
    int steps, i;
    cpFloat dt;
    cpVect look, lastPos, curPos;
    projectile_t *pj; /* temp for looping */

    static cpVect delta = {0, 0};
    static projectile_t *curProj = NULL;
    static bool canToggleEditor = true;

    curPos = atlMousePos();
    lastPos = atlMouseLastPos();

    /* rotate 'gun' based on mouse position */
    look = cpvnormalize(cpvsub(curPos, g_Cannon->body->p));
    cpBodySetAngle(g_Cannon->body, cpvtoangle(look));

    if (isKeyPressed(KEY_e) && canToggleEditor) {
        canToggleEditor = false;
        editorMode = !editorMode;
    } else if (!isKeyPressed(KEY_e)) {
        canToggleEditor = true;
    }

    if (editorMode) {
        if (!editorBody)
            initializeEditor();
        handleEditor();
    } else {
        if (editorBody)
            destroyEditor();

        if (atlLeftMouseDown()) {

            if (!curProj) {
                /* don't let player hold the left mouse button to fire multiple rounds */
                delta = cpvnormalize(cpvsub(atlMouseClickPos(), g_Cannon->body->p));
                if (g_Cannon->ai < MAX_PROJECTILES) {
                    curProj = g_Cannon->ammo[g_Cannon->ai++];

                    if (curProj) {
                        cpSpaceAddBody(g_Space, curProj->body);
                        curProj->body->p = cpvadd(g_Cannon->body->p,
                                                  cpvmult(look, g_Cannon->length));

                        cpSpaceAddShape(g_Space, curProj->shape);
                        cpBodyApplyImpulse(curProj->body,
                                           cpvmult(cpvforangle(g_Cannon->body->a), 600.0f),
                                           cpvzero);
                        cpBodyActivate(curProj->body);
                    }
                }
            }
        } else {
            curProj = NULL;
        }
    }

    /* treat projectiles as limited resources. only allocated at the start of a level */
    for (i = 0; i <= g_Cannon->ai-1; ++i) {
        pj = g_Cannon->ammo[i];
        if (!pj)
            continue;

        if (pj->body->v.x >= -0.01f && pj->body->v.x <= 0.01f &&
            pj->body->v.y >= -0.01f && pj->body->v.y <= 0.01f) {
            /* TODO: mark an object for deletion, but don't delete immediately */
            cpSpaceRemoveBody(g_Space, pj->body);
            cpSpaceRemoveShape(g_Space, pj->shape);
            free(g_Cannon->ammo[i]);
            g_Cannon->ammo[i] = NULL;
        }
    }

    steps = 3;
    dt = 1.0f/60.0f/(cpFloat)steps;

    for (i = 0; i < steps; ++i) {
        cpSpaceStep(g_Space, dt);
    }
}
Пример #7
0
cpBool Buoyancy::WaterPreSolve(cpArbiter *arb, cpSpace *space, void *ptr)
{
    CP_ARBITER_GET_SHAPES(arb, water, poly);
    cpBody *body = cpShapeGetBody(poly);

    // Get the top of the water sensor bounding box to use as the water level.
    cpFloat level = cpShapeGetBB(water).t;

    // Clip the polygon against the water level
    int count = cpPolyShapeGetCount(poly);
    int clippedCount = 0;
#ifdef _MSC_VER
    // MSVC is pretty much the only compiler in existence that doesn't support variable sized arrays.
    cpVect clipped[10];
#else
    cpVect clipped[count + 1];
#endif

    for(int i=0, j=count-1; i<count; j=i, i++){
        cpVect a = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, j));
        cpVect b = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, i));

        if(a.y < level){
            clipped[clippedCount] = a;
            clippedCount++;
        }

        cpFloat a_level = a.y - level;
        cpFloat b_level = b.y - level;

        if(a_level*b_level < 0.0f){
            cpFloat t = cpfabs(a_level)/(cpfabs(a_level) + cpfabs(b_level));

            clipped[clippedCount] = cpvlerp(a, b, t);
            clippedCount++;
        }
    }

    // Calculate buoyancy from the clipped polygon area
    cpFloat clippedArea = cpAreaForPoly(clippedCount, clipped, 0.0f);
    cpFloat displacedMass = clippedArea*FLUID_DENSITY;
    cpVect centroid = cpCentroidForPoly(clippedCount, clipped);

    cpDataPointer data = ptr;
    DrawPolygon(clippedCount, clipped, 0.0f, RGBAColor(0, 0, 1, 1), RGBAColor(0, 0, 1, 0.1f), data);
    DrawDot(5, centroid, RGBAColor(0, 0, 1, 1), data);

    cpFloat dt = cpSpaceGetCurrentTimeStep(space);
    cpVect g = cpSpaceGetGravity(space);

    // Apply the buoyancy force as an impulse.
    cpBodyApplyImpulseAtWorldPoint(body, cpvmult(g, -displacedMass*dt), centroid);

    // Apply linear damping for the fluid drag.
    cpVect v_centroid = cpBodyGetVelocityAtWorldPoint(body, centroid);
    cpFloat k = k_scalar_body(body, centroid, cpvnormalize(v_centroid));
    cpFloat damping = clippedArea*FLUID_DRAG*FLUID_DENSITY;
    cpFloat v_coef = cpfexp(-damping*dt*k); // linear drag
    //	cpFloat v_coef = 1.0/(1.0 + damping*dt*cpvlength(v_centroid)*k); // quadratic drag
    cpBodyApplyImpulseAtWorldPoint(body, cpvmult(cpvsub(cpvmult(v_centroid, v_coef), v_centroid), 1.0/k), centroid);

    // Apply angular damping for the fluid drag.
    cpVect cog = cpBodyLocalToWorld(body, cpBodyGetCenterOfGravity(body));
    cpFloat w_damping = cpMomentForPoly(FLUID_DRAG*FLUID_DENSITY*clippedArea, clippedCount, clipped, cpvneg(cog), 0.0f);
    cpBodySetAngularVelocity(body, cpBodyGetAngularVelocity(body)*cpfexp(-w_damping*dt/cpBodyGetMoment(body)));

    return cpTrue;
}