initial physics constraints

This commit is contained in:
John Alanbrook 2023-12-28 23:38:17 +00:00
parent 192c253f12
commit 5bdf311da9
6 changed files with 71 additions and 26 deletions

View file

@ -1245,6 +1245,7 @@ Object.defineProperty(Number.prototype, 'lerp', {
Math.clamp = function (x, l, h) { return x > h ? h : x < l ? l : x; }
Math.random_range = function(min,max) { return Math.random() * (max-min) + min; };
Math.rand_int = function(max) { return Math.floor(Math.random()*max); };
Math.snap = function(val, grid) {
if (!grid || grid === 1) return Math.round(val);

View file

@ -193,6 +193,19 @@ var gameobject = {
full_path() {
return this.path_from(Primum);
},
/* pin this object to the to object */
pin(to) {
var p = cmd(222,this.body, to.body);
},
pivot(to, piv) {
piv ??= this.worldpos();
var p = cmd(221,this.body,to.body,piv);
},
gear(to, phase, ratio) {
phase ??= 1;
ratio ??= 1;
var p = cmd(223,this.body,to.body,phase,ratio);
},
path_from(o) {
var p = this.toString();
@ -517,7 +530,8 @@ var gameobject = {
Player.do_uncontrol(this);
Register.unregister_obj(this);
this.__proto__.instances.remove(this);
if (this.__proto__.instances)
this.__proto__.instances.remove(this);
for (var key in this.components) {
Register.unregister_obj(this.components[key]);

View file

@ -213,10 +213,9 @@ struct phys2d_circle *Make2DCircle(gameobject *go) {
return new;
}
float phys2d_circle_moi(struct phys2d_circle *c, float m) {
return 1;
//TODO: Calculate correctly
//return cpMomentForCircle(m, 0, c->radius, c->offset);
float phys2d_circle_moi(struct phys2d_circle *c) {
float m = c->shape.go->mass;
return cpMomentForCircle(m, 0, cpCircleShapeGetRadius(c->shape.shape), cpCircleShapeGetOffset(c->shape.shape));
}
void phys2d_circledel(struct phys2d_circle *c) {
@ -233,6 +232,18 @@ void phys2d_dbgdrawcpcirc(cpShape *c) {
draw_circle(pos,radius,radius,color,-1);
}
void phys2d_shape_apply(struct phys2d_shape *s)
{
float moment = cpBodyGetMoment(s->go->body);
float moi = s->moi(s->data);
s->apply(s->data);
float newmoi = s->moi(s->data);
moment-=moi;
moment += newmoi;
cpBodySetMoment(s->go->body, moment);
}
void phys2d_dbgdrawcircle(struct phys2d_circle *circle) {
phys2d_dbgdrawcpcirc(circle->shape.shape);
}
@ -268,12 +279,16 @@ void phys2d_poly_free(struct phys2d_poly *poly)
free(poly);
}
float phys2d_poly_moi(struct phys2d_poly *poly, float m) {
float moi = cpMomentForPoly(m, arrlen(poly->points), (cpVect*)poly->points, cpvzero, poly->radius);
if (isnan(moi)) {
// YughError("Polygon MOI returned an error. Returning 0.");
float phys2d_poly_moi(struct phys2d_poly *poly) {
float m = poly->shape.go->mass;
int len = cpPolyShapeGetCount(poly->shape.shape);
cpVect points[len];
for (int i = 0; i < len; i++)
points[i] = cpPolyShapeGetVert(poly->shape.shape, i);
float moi = cpMomentForPoly(m, len, points, cpvzero, poly->radius);
if (!isfinite(moi))
return 0;
}
return moi;
}
@ -297,7 +312,7 @@ void phys2d_poly_setverts(struct phys2d_poly *poly, HMM_Vec2 *verts) {
for (int i = 0; i < arrlen(verts); i++)
poly->points[i] = verts[i];
phys2d_applypoly(poly);
phys2d_shape_apply(&poly->shape);
}
void phys2d_applypoly(struct phys2d_poly *poly) {
@ -365,7 +380,8 @@ void phys2d_edge_free(struct phys2d_edge *edge)
free(edge);
}
float phys2d_edge_moi(struct phys2d_edge *edge, float m) {
float phys2d_edge_moi(struct phys2d_edge *edge) {
float m = edge->shape.go->mass;
float moi = 0;
for (int i = 0; i < arrlen(edge->points) - 1; i++)
moi += cpMomentForSegment(m, edge->points[i].cp, edge->points[i + 1].cp, edge->thickness);

View file

@ -23,11 +23,13 @@ struct phys2d_shape {
gameobject *go;
void *data; /* The specific subtype; phys2d_circle, etc */
void (*debugdraw)(void *data);
float (*moi)(void *data, float mass);
float (*moi)(void *data);
void (*apply)(void *data);
void (*free)(void *data);
};
void phys2d_shape_apply(struct phys2d_shape *s);
/* Circles are the fastest colldier type */
struct phys2d_circle {
float radius;
@ -56,7 +58,7 @@ struct phys2d_circle *Make2DCircle(gameobject *go);
void phys2d_circledel(struct phys2d_circle *c);
void phys2d_applycircle(struct phys2d_circle *circle);
void phys2d_dbgdrawcircle(struct phys2d_circle *circle);
float phys2d_circle_moi(struct phys2d_circle *c, float m);
float phys2d_circle_moi(struct phys2d_circle *c);
struct phys2d_poly *Make2DPoly(gameobject *go);
void phys2d_poly_free(struct phys2d_poly *poly);
@ -65,7 +67,7 @@ void phys2d_applypoly(struct phys2d_poly *poly);
void phys2d_dbgdrawpoly(struct phys2d_poly *poly);
void phys2d_polyaddvert(struct phys2d_poly *poly);
void phys2d_poly_setverts(struct phys2d_poly *poly, HMM_Vec2 *verts);
float phys2d_poly_moi(struct phys2d_poly *poly, float m);
float phys2d_poly_moi(struct phys2d_poly *poly);
struct phys2d_edge *Make2DEdge(gameobject *go);
void phys2d_edge_free(struct phys2d_edge *edge);
@ -74,7 +76,7 @@ void phys2d_applyedge(struct phys2d_edge *edge);
void phys2d_dbgdrawedge(struct phys2d_edge *edge);
void phys2d_edgeaddvert(struct phys2d_edge *edge, HMM_Vec2 v);
void phys2d_edge_rmvert(struct phys2d_edge *edge, int index);
float phys2d_edge_moi(struct phys2d_edge *edge, float m);
float phys2d_edge_moi(struct phys2d_edge *edge);
void phys2d_edge_setvert(struct phys2d_edge *edge, int index, cpVect val);
void phys2d_edge_clearverts(struct phys2d_edge *edge);

View file

@ -93,16 +93,16 @@ void go_shape_apply(cpBody *body, cpShape *shape, gameobject *go) {
}
void go_shape_moi(cpBody *body, cpShape *shape, gameobject *go) {
float moment = cpBodyGetMoment(go->body);
float moment = cpBodyGetMoment(body);
struct phys2d_shape *s = cpShapeGetUserData(shape);
if (!s) {
cpBodySetMoment(go->body, moment + 1);
cpBodySetMoment(body, moment + 1);
return;
}
moment += s->moi(s->data, go->mass);
if (moment < 0) moment = 1;
cpBodySetMoment(go->body, 1);
moment += s->moi(s->data);
if (moment < 0) moment = 0;
cpBodySetMoment(body, moment);
}
void gameobject_apply(gameobject *go) {

View file

@ -1370,6 +1370,18 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 220:
ret = num2js(js2sprite(argv[1])->drawmode);
break;
case 221:
ret = ptr2js(cpPivotJointNew(js2gameobject(argv[1])->body, js2gameobject(argv[2])->body,js2vec2(argv[3]).cp));
cpSpaceAddConstraint(space,js2ptr(ret));
break;
case 222:
ret = ptr2js(cpPinJointNew(js2gameobject(argv[1])->body, js2gameobject(argv[2])->body, cpvzero,cpvzero));
cpSpaceAddConstraint(space, js2ptr(ret));
break;
case 223:
ret = ptr2js(cpGearJointNew(js2gameobject(argv[1])->body, js2gameobject(argv[2])->body, js2number(argv[3]), js2number(argv[4])));
cpSpaceAddConstraint(space,js2ptr(ret));
break;
}
if (str)
@ -1706,8 +1718,8 @@ JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCons
case 3:
return vec2js(circle->offset);
}
phys2d_shape_apply(&circle->shape);
phys2d_applycircle(circle);
return JS_UNDEFINED;
}