static struct cpShapeMassInfo cpSegmentShapeMassInfo(cpFloat mass, cpVect a, cpVect b, cpFloat r) { struct cpShapeMassInfo info = { mass, cpMomentForBox(1.0f, cpvdist(a, b) + 2.0f*r, 2.0f*r), // TODO is an approximation. cpvlerp(a, b, 0.5f), cpAreaForSegment(a, b, r), }; return info; }
static cpBody *utils_update_drawing(cpBody *drawing) { cpFloat mass = cpBodyGetMass(drawing); cpFloat moment = cpBodyGetMoment(drawing); Body_data *pa = cpBodyGetUserData(drawing); //cpFloat x = g_array_index(pa->x_values, cpFloat, 0); //cpFloat y = g_array_index(pa->y_values, cpFloat, 0); cpVect pos_a, pos_b; cpVect origin = cpBodyGetPos(drawing); cpFloat mi, micx = 0, micy = 0; int length = pa->x_values->len; for (int index = 1; index < length; index++) { pos_a = cpv(g_array_index(pa->x_values, cpFloat, index - 1), g_array_index(pa->y_values, cpFloat, index - 1)); pos_b = cpv(g_array_index(pa->x_values, cpFloat, index), g_array_index(pa->y_values, cpFloat, index)); //fprintf(stdout, "Pos_a = (%5.2f, %5.2f)\n", pos_a.x, pos_a.y); mi = (CRAYON_MASS * cpAreaForSegment( pos_a, pos_b, CRAYON_RADIUS )); micx += mi * ((pos_a.x + pos_b.x) / 2); micy += mi * ((pos_a.y + pos_b.y) / 2); mass += mi; moment += cpMomentForSegment(mass, pos_a, pos_b); // not actually sum, but maybe it is } cpBodySetMass(drawing, mass); cpBodySetMoment(drawing, moment); // center of mass is the average of all vertices NOT //cpVect new_origin = cpv(x / length, y / length); cpVect new_origin = cpv(micx / mass, micy / mass); new_origin = cpBodyLocal2World(drawing, new_origin); cpBodySetPos( drawing, new_origin ); //fprintf(stdout, "Position set at (%5.2f, %5.2f)\n", new_origin.x, new_origin.y); cpSpace * space = cpBodyGetSpace(drawing); cpSpaceReindexShapesForBody(space, drawing); //cpBodySetPos(drawing, cpv(pos.x + (second.x / length), pos.y + (second.y / length))); //pa->offset = cpvsub(new_origin, origin); pa = shift_origin(drawing, origin, new_origin); cpBodySetUserData(drawing, pa); if (space) post_step_body_replace_shapes(space, drawing, NULL); else fprintf(stderr, "WTF\n"); //if (!(cpSpaceAddPostStepCallback(space, (cpPostStepFunc) post_step_body_replace_shapes, drawing, NULL))) //fprintf(stderr, "FAILED POST-STEP CALLBACK\n\n"); return drawing; }
/** @name areaForSegment @text Returns the area for the specified segment. @in number x1 @in number y1 @in number x2 @in number y2 @in number r @out number area The calculated area. */ int MOAICpShape::_areaForSegment ( lua_State* L ) { USLuaState state ( L ); if ( !state.CheckParams ( 1, "UUNNNN" )) return 0; cpVect a; a.x = state.GetValue < cpFloat >( 1, 0 ); a.y = state.GetValue < cpFloat >( 2, 0 ); cpVect b; b.x = state.GetValue < cpFloat >( 3, 0 ); b.y = state.GetValue < cpFloat >( 4, 0 ); cpFloat r = state.GetValue < cpFloat >( 5, 0 ); lua_pushnumber ( L, cpAreaForSegment ( a, b, r )); return 1; }
static cpBody *utils_update_drawing(cpBody *drawing) { cpFloat mass = cpBodyGetMass(drawing); cpFloat moment = cpBodyGetMoment(drawing); Point_array *pa = cpBodyGetUserData(drawing); cpFloat x = g_array_index(pa->x_values, cpFloat, 0); cpFloat y = g_array_index(pa->y_values, cpFloat, 0); cpVect pos_a, pos_b; cpVect origin = cpBodyGetPos(drawing); cpFloat mi, micx = 0, micy = 0; int length = pa->x_values->len; for (int index = 1; index < length; index++) { pos_a = cpv(g_array_index(pa->x_values, cpFloat, index - 1), g_array_index(pa->y_values, cpFloat, index - 1)); pos_b = cpv(g_array_index(pa->x_values, cpFloat, index), g_array_index(pa->y_values, cpFloat, index)); cpvadd(pos_a, origin); cpvadd(pos_b, origin); x += pos_b.x; y += pos_b.y; mi = (CRAYON_MASS * cpAreaForSegment( pos_a, pos_b, CRAYON_RADIUS )); micx += mi * ((pos_a.x + pos_b.x) / 2); micy += mi * ((pos_a.y + pos_b.y) / 2); mass += mi; moment += cpMomentForSegment(mass, pos_a, pos_b); // not actually sum } cpBodySetMass(drawing, mass); cpBodySetMoment(drawing, moment); // center of mass is the average of all vertices NOT //cpVect new_origin = cpv(x / length, y / length); cpVect new_origin = cpv(micx / mass, micy / mass); cpBodySetPos( drawing, new_origin ); //cpBodySetPos(drawing, cpv(pos.x + (second.x / length), pos.y + (second.y / length))); pa = shift_origin(pa, origin, new_origin); cpBodySetUserData(drawing, pa); return drawing; }
cpFloat Area::ForSegment( cVect a, cVect b, cpFloat r ) { return cpAreaForSegment( tocpv( a ), tocpv( b ), r ); }
__declspec( dllexport ) void areaforsegment( const void * _in, int in_size, void * _out, int out_sz ) { POKEFLOAT(OUTPUT_MEMBLOCK,0,cpAreaForSegment(PEEKVECT(INPUT_MEMBLOCK,0),PEEKVECT(INPUT_MEMBLOCK,8),PEEKFLOAT(INPUT_MEMBLOCK,16))); }
static VALUE rb_cpAreaForSegment(VALUE self, VALUE v1, VALUE v2, VALUE r) { cpFloat i = cpAreaForSegment(*VGET(v1), *VGET(v2), NUM2DBL(r)); return rb_float_new(i); }