Get/set World and Joint simulation parameters

Tightness parameter is amount of force is exerted on collider to resolve
collisions and enforce joint operation. Low values make joints loose,
high values make it tight and can cause collider to overshot the joint
target. With tightness set to 0 the joint loses its function. Going
above 1 puts even more energy into joint oscillations. Tightness
parameter is called ERP in ODE manual.

The responseTime affects the time constant of physics simulation, both
for collisions and for joint inertia. Low responseTime values make
simulation tight and fast, higher values make it sluggish. For
collisions it affects how fast penetration is resolved, with higher
values resulting in spongy objects with more surface penetration and
slower collision resolving. For joints the responseTime is similar to
inertia, with higher responseTime values resulting in slow oscillations.
The oscillation frequency is also affected by collider mass, so
responseTime can be used to tweak the joint to get desired frequency
with specific collider mass. Values higher than 1 are often desirable,
especially for very light objects. Unlike tightness, responseTime is
tweaked in orders of magnitude with useful values (depending on mass)
being between 10^-8 and 10^8.

Both parameters can be applied to World for simulation-wide usage, or
specified per-joint in case of distance and ball joints. Other joints
don't allow customizing these parameters, and will use World settings
instead..
This commit is contained in:
Josip Miskovic 2020-05-29 17:38:32 +03:00
parent ada79dbf5d
commit 139808cab0
4 changed files with 160 additions and 0 deletions

View File

@ -122,10 +122,42 @@ static int l_lovrBallJointSetAnchor(lua_State* L) {
return 0;
}
static int l_lovrBallJointGetResponseTime(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float responseTime = lovrBallJointGetResponseTime(joint);
lua_pushnumber(L, responseTime);
return 1;
}
static int l_lovrBallJointSetResponseTime(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float responseTime = luax_checkfloat(L, 2);
lovrBallJointSetResponseTime(joint, responseTime);
return 0;
}
static int l_lovrBallJointGetTightness(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float tightness = lovrBallJointGetTightness(joint);
lua_pushnumber(L, tightness);
return 1;
}
static int l_lovrBallJointSetTightness(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float tightness = luax_checkfloat(L, 2);
lovrBallJointSetTightness(joint, tightness);
return 0;
}
const luaL_Reg lovrBallJoint[] = {
lovrJoint,
{ "getAnchors", l_lovrBallJointGetAnchors },
{ "setAnchor", l_lovrBallJointSetAnchor },
{ "getResponseTime", l_lovrBallJointGetResponseTime},
{ "setResponseTime", l_lovrBallJointSetResponseTime},
{ "getTightness", l_lovrBallJointGetTightness},
{ "setTightness", l_lovrBallJointSetTightness},
{ NULL, NULL }
};
@ -164,12 +196,44 @@ static int l_lovrDistanceJointSetDistance(lua_State* L) {
return 0;
}
static int l_lovrDistanceJointGetResponseTime(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float responseTime = lovrDistanceJointGetResponseTime(joint);
lua_pushnumber(L, responseTime);
return 1;
}
static int l_lovrDistanceJointSetResponseTime(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float responseTime = luax_checkfloat(L, 2);
lovrDistanceJointSetResponseTime(joint, responseTime);
return 0;
}
static int l_lovrDistanceJointGetTightness(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float tightness = lovrDistanceJointGetTightness(joint);
lua_pushnumber(L, tightness);
return 1;
}
static int l_lovrDistanceJointSetTightness(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
float tightness = luax_checkfloat(L, 2);
lovrDistanceJointSetTightness(joint, tightness);
return 0;
}
const luaL_Reg lovrDistanceJoint[] = {
lovrJoint,
{ "getAnchors", l_lovrDistanceJointGetAnchors },
{ "setAnchors", l_lovrDistanceJointSetAnchors },
{ "getDistance", l_lovrDistanceJointGetDistance },
{ "setDistance", l_lovrDistanceJointSetDistance },
{ "getResponseTime", l_lovrDistanceJointGetResponseTime},
{ "setResponseTime", l_lovrDistanceJointSetResponseTime},
{ "getTightness", l_lovrDistanceJointGetTightness},
{ "setTightness", l_lovrDistanceJointSetTightness},
{ NULL, NULL }
};

View File

@ -187,6 +187,34 @@ static int l_lovrWorldSetGravity(lua_State* L) {
return 0;
}
static int l_lovrWorldGetTightness(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float tightness = lovrWorldGetTightness(world);
lua_pushnumber(L, tightness);
return 1;
}
static int l_lovrWorldSetTightness(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float tightness = luax_checkfloat(L, 2);
lovrWorldSetTightness(world, tightness);
return 0;
}
static int l_lovrWorldGetResponseTime(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float responseTime = lovrWorldGetResponseTime(world);
lua_pushnumber(L, responseTime);
return 1;
}
static int l_lovrWorldSetResponseTime(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float responseTime = luax_checkfloat(L, 2);
lovrWorldSetResponseTime(world, responseTime);
return 0;
}
static int l_lovrWorldGetLinearDamping(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float damping, threshold;
@ -284,6 +312,10 @@ const luaL_Reg lovrWorld[] = {
{ "collide", l_lovrWorldCollide },
{ "getGravity", l_lovrWorldGetGravity },
{ "setGravity", l_lovrWorldSetGravity },
{ "getTightness", l_lovrWorldGetTightness },
{ "setTightness", l_lovrWorldSetTightness },
{ "getResponseTime", l_lovrWorldGetResponseTime },
{ "setResponseTime", l_lovrWorldSetResponseTime },
{ "getLinearDamping", l_lovrWorldGetLinearDamping },
{ "setLinearDamping", l_lovrWorldSetLinearDamping },
{ "getAngularDamping", l_lovrWorldGetAngularDamping },

View File

@ -195,6 +195,22 @@ void lovrWorldSetGravity(World* world, float x, float y, float z) {
dWorldSetGravity(world->id, x, y, z);
}
float lovrWorldGetResponseTime(World* world) {
return dWorldGetCFM(world->id);
}
void lovrWorldSetResponseTime(World* world, float responseTime) {
dWorldSetCFM(world->id, responseTime);
}
float lovrWorldGetTightness(World* world) {
return dWorldGetERP(world->id);
}
void lovrWorldSetTightness(World* world, float tightness) {
dWorldSetERP(world->id, tightness);
}
void lovrWorldGetLinearDamping(World* world, float* damping, float* threshold) {
*damping = dWorldGetLinearDamping(world->id);
*threshold = dWorldGetLinearDampingThreshold(world->id);
@ -954,6 +970,22 @@ void lovrBallJointSetAnchor(BallJoint* joint, float x, float y, float z) {
dJointSetBallAnchor(joint->id, x, y, z);
}
float lovrBallJointGetResponseTime(Joint* joint) {
return dJointGetBallParam(joint->id, dParamCFM);
}
void lovrBallJointSetResponseTime(Joint* joint, float responseTime) {
dJointSetBallParam(joint->id, dParamCFM, responseTime);
}
float lovrBallJointGetTightness(Joint* joint) {
return dJointGetBallParam(joint->id, dParamERP);
}
void lovrBallJointSetTightness(Joint* joint, float tightness) {
dJointSetBallParam(joint->id, dParamERP, tightness);
}
DistanceJoint* lovrDistanceJointInit(DistanceJoint* joint, Collider* a, Collider* b, float x1, float y1, float z1, float x2, float y2, float z2) {
lovrAssert(a->world == b->world, "Joint bodies must exist in same World");
joint->type = JOINT_DISTANCE;
@ -990,6 +1022,22 @@ void lovrDistanceJointSetDistance(DistanceJoint* joint, float distance) {
dJointSetDBallDistance(joint->id, distance);
}
float lovrDistanceJointGetResponseTime(Joint* joint) {
return dJointGetDBallParam(joint->id, dParamCFM);
}
void lovrDistanceJointSetResponseTime(Joint* joint, float responseTime) {
dJointSetDBallParam(joint->id, dParamCFM, responseTime);
}
float lovrDistanceJointGetTightness(Joint* joint) {
return dJointGetDBallParam(joint->id, dParamERP);
}
void lovrDistanceJointSetTightness(Joint* joint, float tightness) {
dJointSetDBallParam(joint->id, dParamERP, tightness);
}
HingeJoint* lovrHingeJointInit(HingeJoint* joint, Collider* a, Collider* b, float x, float y, float z, float ax, float ay, float az) {
lovrAssert(a->world == b->world, "Joint bodies must exist in same World");
joint->type = JOINT_HINGE;

View File

@ -97,6 +97,10 @@ int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float res
Collider* lovrWorldGetFirstCollider(World* world);
void lovrWorldGetGravity(World* world, float* x, float* y, float* z);
void lovrWorldSetGravity(World* world, float x, float y, float z);
float lovrWorldGetResponseTime(World* world);
void lovrWorldSetResponseTime(World* world, float responseTime);
float lovrWorldGetTightness(World* world);
void lovrWorldSetTightness(World* world, float tightness);
void lovrWorldGetLinearDamping(World* world, float* damping, float* threshold);
void lovrWorldSetLinearDamping(World* world, float damping, float threshold);
void lovrWorldGetAngularDamping(World* world, float* damping, float* threshold);
@ -211,6 +215,10 @@ void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length);
void lovrJointDestroy(void* ref);
void lovrJointDestroyData(Joint* joint);
JointType lovrJointGetType(Joint* joint);
float lovrJointGetCFM(Joint* joint);
void lovrJointSetCFM(Joint* joint, float cfm);
float lovrJointGetERP(Joint* joint);
void lovrJointSetERP(Joint* joint, float erp);
void lovrJointGetColliders(Joint* joint, Collider** a, Collider** b);
void* lovrJointGetUserData(Joint* joint);
void lovrJointSetUserData(Joint* joint, void* data);
@ -222,6 +230,10 @@ BallJoint* lovrBallJointInit(BallJoint* joint, Collider* a, Collider* b, float x
#define lovrBallJointDestroy lovrJointDestroy
void lovrBallJointGetAnchors(BallJoint* joint, float* x1, float* y1, float* z1, float* x2, float* y2, float* z2);
void lovrBallJointSetAnchor(BallJoint* joint, float x, float y, float z);
float lovrBallJointGetResponseTime(Joint* joint);
void lovrBallJointSetResponseTime(Joint* joint, float responseTime);
float lovrBallJointGetTightness(Joint* joint);
void lovrBallJointSetTightness(Joint* joint, float tightness);
DistanceJoint* lovrDistanceJointInit(DistanceJoint* joint, Collider* a, Collider* b, float x1, float y1, float z1, float x2, float y2, float z2);
#define lovrDistanceJointCreate(...) lovrDistanceJointInit(lovrAlloc(DistanceJoint), __VA_ARGS__)
@ -230,6 +242,10 @@ void lovrDistanceJointGetAnchors(DistanceJoint* joint, float* x1, float* y1, flo
void lovrDistanceJointSetAnchors(DistanceJoint* joint, float x1, float y1, float z1, float x2, float y2, float z2);
float lovrDistanceJointGetDistance(DistanceJoint* joint);
void lovrDistanceJointSetDistance(DistanceJoint* joint, float distance);
float lovrDistanceJointGetResponseTime(Joint* joint);
void lovrDistanceJointSetResponseTime(Joint* joint, float responseTime);
float lovrDistanceJointGetTightness(Joint* joint);
void lovrDistanceJointSetTightness(Joint* joint, float tightness);
HingeJoint* lovrHingeJointInit(HingeJoint* joint, Collider* a, Collider* b, float x, float y, float z, float ax, float ay, float az);
#define lovrHingeJointCreate(...) lovrHingeJointInit(lovrAlloc(HingeJoint), __VA_ARGS__)