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.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.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) { Math.snap = function(val, grid) {
if (!grid || grid === 1) return Math.round(val); if (!grid || grid === 1) return Math.round(val);

View file

@ -193,6 +193,19 @@ var gameobject = {
full_path() { full_path() {
return this.path_from(Primum); 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) { path_from(o) {
var p = this.toString(); var p = this.toString();
@ -517,6 +530,7 @@ var gameobject = {
Player.do_uncontrol(this); Player.do_uncontrol(this);
Register.unregister_obj(this); Register.unregister_obj(this);
if (this.__proto__.instances)
this.__proto__.instances.remove(this); this.__proto__.instances.remove(this);
for (var key in this.components) { for (var key in this.components) {

View file

@ -213,10 +213,9 @@ struct phys2d_circle *Make2DCircle(gameobject *go) {
return new; return new;
} }
float phys2d_circle_moi(struct phys2d_circle *c, float m) { float phys2d_circle_moi(struct phys2d_circle *c) {
return 1; float m = c->shape.go->mass;
//TODO: Calculate correctly return cpMomentForCircle(m, 0, cpCircleShapeGetRadius(c->shape.shape), cpCircleShapeGetOffset(c->shape.shape));
//return cpMomentForCircle(m, 0, c->radius, c->offset);
} }
void phys2d_circledel(struct phys2d_circle *c) { void phys2d_circledel(struct phys2d_circle *c) {
@ -233,6 +232,18 @@ void phys2d_dbgdrawcpcirc(cpShape *c) {
draw_circle(pos,radius,radius,color,-1); 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) { void phys2d_dbgdrawcircle(struct phys2d_circle *circle) {
phys2d_dbgdrawcpcirc(circle->shape.shape); phys2d_dbgdrawcpcirc(circle->shape.shape);
} }
@ -268,12 +279,16 @@ void phys2d_poly_free(struct phys2d_poly *poly)
free(poly); free(poly);
} }
float phys2d_poly_moi(struct phys2d_poly *poly, float m) { float phys2d_poly_moi(struct phys2d_poly *poly) {
float moi = cpMomentForPoly(m, arrlen(poly->points), (cpVect*)poly->points, cpvzero, poly->radius); float m = poly->shape.go->mass;
if (isnan(moi)) { int len = cpPolyShapeGetCount(poly->shape.shape);
// YughError("Polygon MOI returned an error. Returning 0."); 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 0;
}
return moi; 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++) for (int i = 0; i < arrlen(verts); i++)
poly->points[i] = verts[i]; poly->points[i] = verts[i];
phys2d_applypoly(poly); phys2d_shape_apply(&poly->shape);
} }
void phys2d_applypoly(struct phys2d_poly *poly) { void phys2d_applypoly(struct phys2d_poly *poly) {
@ -365,7 +380,8 @@ void phys2d_edge_free(struct phys2d_edge *edge)
free(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; float moi = 0;
for (int i = 0; i < arrlen(edge->points) - 1; i++) for (int i = 0; i < arrlen(edge->points) - 1; i++)
moi += cpMomentForSegment(m, edge->points[i].cp, edge->points[i + 1].cp, edge->thickness); 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; gameobject *go;
void *data; /* The specific subtype; phys2d_circle, etc */ void *data; /* The specific subtype; phys2d_circle, etc */
void (*debugdraw)(void *data); void (*debugdraw)(void *data);
float (*moi)(void *data, float mass); float (*moi)(void *data);
void (*apply)(void *data); void (*apply)(void *data);
void (*free)(void *data); void (*free)(void *data);
}; };
void phys2d_shape_apply(struct phys2d_shape *s);
/* Circles are the fastest colldier type */ /* Circles are the fastest colldier type */
struct phys2d_circle { struct phys2d_circle {
float radius; float radius;
@ -56,7 +58,7 @@ struct phys2d_circle *Make2DCircle(gameobject *go);
void phys2d_circledel(struct phys2d_circle *c); void phys2d_circledel(struct phys2d_circle *c);
void phys2d_applycircle(struct phys2d_circle *circle); void phys2d_applycircle(struct phys2d_circle *circle);
void phys2d_dbgdrawcircle(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); struct phys2d_poly *Make2DPoly(gameobject *go);
void phys2d_poly_free(struct phys2d_poly *poly); 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_dbgdrawpoly(struct phys2d_poly *poly);
void phys2d_polyaddvert(struct phys2d_poly *poly); void phys2d_polyaddvert(struct phys2d_poly *poly);
void phys2d_poly_setverts(struct phys2d_poly *poly, HMM_Vec2 *verts); 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); struct phys2d_edge *Make2DEdge(gameobject *go);
void phys2d_edge_free(struct phys2d_edge *edge); 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_dbgdrawedge(struct phys2d_edge *edge);
void phys2d_edgeaddvert(struct phys2d_edge *edge, HMM_Vec2 v); void phys2d_edgeaddvert(struct phys2d_edge *edge, HMM_Vec2 v);
void phys2d_edge_rmvert(struct phys2d_edge *edge, int index); 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_setvert(struct phys2d_edge *edge, int index, cpVect val);
void phys2d_edge_clearverts(struct phys2d_edge *edge); 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) { 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); struct phys2d_shape *s = cpShapeGetUserData(shape);
if (!s) { if (!s) {
cpBodySetMoment(go->body, moment + 1); cpBodySetMoment(body, moment + 1);
return; return;
} }
moment += s->moi(s->data, go->mass); moment += s->moi(s->data);
if (moment < 0) moment = 1; if (moment < 0) moment = 0;
cpBodySetMoment(go->body, 1); cpBodySetMoment(body, moment);
} }
void gameobject_apply(gameobject *go) { void gameobject_apply(gameobject *go) {

View file

@ -1370,6 +1370,18 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 220: case 220:
ret = num2js(js2sprite(argv[1])->drawmode); ret = num2js(js2sprite(argv[1])->drawmode);
break; 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) if (str)
@ -1706,8 +1718,8 @@ JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCons
case 3: case 3:
return vec2js(circle->offset); return vec2js(circle->offset);
} }
phys2d_shape_apply(&circle->shape);
phys2d_applycircle(circle);
return JS_UNDEFINED; return JS_UNDEFINED;
} }