Shape fixes;

- Collider always has Shape now.  When left off or set to null, it's a
  tiny sphere (representing a point).
- Preserve shape offset when changing shape.
This commit is contained in:
bjorn 2024-04-05 18:40:23 -07:00
parent f82715d402
commit 24708f7114
1 changed files with 46 additions and 30 deletions

View File

@ -43,6 +43,7 @@ struct Joint {
static struct {
bool initialized;
Shape* pointShape;
JPH_Shape* queryBox;
JPH_Shape* querySphere;
JPH_AllHit_CastShapeCollector* castShapeCollector;
@ -69,14 +70,16 @@ static uint32_t findTag(World* world, const char* name) {
bool lovrPhysicsInit(void) {
if (state.initialized) return false;
JPH_Init(32 * 1024 * 1024);
state.castShapeCollector = JPH_AllHit_CastShapeCollector_Create();
state.pointShape = lovrSphereShapeCreate(FLT_EPSILON);
state.querySphere = (JPH_Shape*) JPH_SphereShape_Create(1.f);
state.queryBox = (JPH_Shape*) JPH_BoxShape_Create(&(const JPH_Vec3) { .5, .5f, .5f }, 0.f);
state.castShapeCollector = JPH_AllHit_CastShapeCollector_Create();
return state.initialized = true;
}
void lovrPhysicsDestroy(void) {
if (!state.initialized) return;
lovrRelease(state.pointShape, lovrShapeDestroy);
JPH_Shutdown();
state.initialized = false;
}
@ -320,23 +323,26 @@ Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float
uint32_t limit = JPH_PhysicsSystem_GetMaxBodies(world->system);
lovrCheck(count < limit, "Too many colliders!");
if (!shape) shape = state.pointShape;
Collider* collider = lovrCalloc(sizeof(Collider));
collider->ref = 1;
collider->world = world;
collider->shape = shape;
collider->tag = UNTAGGED;
JPH_MotionType motionType = JPH_MotionType_Dynamic;
JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1;
const JPH_RVec3 position = { x, y, z };
const JPH_Quat rotation = { 0.f, 0.f, 0.f, 1.f };
// todo: a placeholder querySphere shape is used in collider, then replaced in lovrColliderAddShape
JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(
shape ? shape->shape : state.querySphere, &position, &rotation, motionType, objectLayer);
JPH_MotionType type = JPH_MotionType_Dynamic;
JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1;
JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(shape->shape, &position, &rotation, type, objectLayer);
collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings);
JPH_BodyCreationSettings_Destroy(settings);
collider->id = JPH_Body_GetID(collider->body);
JPH_BodyCreationSettings_Destroy(settings);
JPH_BodyInterface_AddBody(world->bodies, collider->id, JPH_Activation_Activate);
JPH_BodyInterface_SetUserData(world->bodies, collider->id, (uint64_t) collider);
lovrColliderSetLinearDamping(collider, world->defaultLinearDamping, 0.f);
lovrColliderSetAngularDamping(collider, world->defaultAngularDamping, 0.f);
lovrColliderSetSleepingAllowed(collider, world->defaultIsSleepingAllowed);
@ -352,8 +358,8 @@ Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float
world->head = collider;
}
// The world owns a reference to the collider
lovrRetain(collider);
lovrRetain(collider->shape);
lovrRetain(collider); // The world owns a reference to the collider
return collider;
}
@ -406,22 +412,35 @@ Collider* lovrColliderGetNext(Collider* collider) {
}
Shape* lovrColliderGetShape(Collider* collider) {
return collider->shape;
return collider->shape == state.pointShape ? NULL : collider->shape;
}
void lovrColliderSetShape(Collider* collider, Shape* shape) {
if (shape != collider->shape) {
lovrRelease(collider->shape, lovrShapeDestroy);
collider->shape = shape;
lovrRetain(shape);
shape = shape ? shape : state.pointShape;
bool updateMass = true;
if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) {
lovrColliderSetKinematic(collider, true);
updateMass = false;
}
if (shape == collider->shape) {
return;
}
JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, updateMass, JPH_Activation_Activate);
float position[3], orientation[4];
const JPH_Shape* parent = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id);
bool hasOffset = JPH_Shape_GetSubType(parent) == JPH_ShapeSubType_RotatedTranslated;
if (hasOffset) lovrColliderGetShapeOffset(collider, position, orientation);
lovrRelease(collider->shape, lovrShapeDestroy);
collider->shape = shape;
lovrRetain(shape);
bool updateMass = true;
if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) {
lovrColliderSetKinematic(collider, true);
updateMass = false;
}
JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, updateMass, JPH_Activation_Activate);
if (hasOffset) {
lovrColliderSetShapeOffset(collider, position, orientation);
}
}
@ -451,7 +470,7 @@ void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orie
JPH_Vec3 jposition = { position[0], position[1], position[2] };
JPH_Quat jrotation = { orientation[0], orientation[1], orientation[2], orientation[3] };
shape = (JPH_Shape*) JPH_RotatedTranslatedShape_Create(&jposition, &jrotation, collider->shape->shape);
bool updateMass = collider->shape->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN;
bool updateMass = collider->shape && (collider->shape->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN);
JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape, updateMass, JPH_Activation_Activate);
}
@ -557,20 +576,17 @@ void lovrColliderSetAwake(Collider* collider, bool awake) {
}
float lovrColliderGetMass(Collider* collider) {
if (!collider->shape) return 0.f;
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties);
}
void lovrColliderSetMass(Collider* collider, float mass) {
if (collider->shape) {
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
Shape* shape = collider->shape;
JPH_MassProperties* massProperties;
JPH_Shape_GetMassProperties(shape->shape, massProperties);
JPH_MassProperties_ScaleToMass(massProperties, mass);
JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties);
}
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
Shape* shape = collider->shape;
JPH_MassProperties* massProperties;
JPH_Shape_GetMassProperties(shape->shape, massProperties);
JPH_MassProperties_ScaleToMass(massProperties, mass);
JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties);
}
void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {