Skip to content

Commit 2fd4c67

Browse files
feat: handle zero triangles in createConcaveShapeSettingsFromPart
1 parent e57cac6 commit 2fd4c67

File tree

2 files changed

+65
-8
lines changed

2 files changed

+65
-8
lines changed

fission/src/mirabuf/MirabufSceneObject.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,9 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
511511
let totalMass = 0
512512
this._mirabufInstance.parser.rigidNodes.forEach(rn => {
513513
if (!this._mirabufInstance.meshes.size) return // if this.dispose() has been ran then return
514-
const body = World.physicsSystem.getBody(this._mechanism.getBodyByNodeId(rn.id)!)
514+
const bodyId = this._mechanism.getBodyByNodeId(rn.id)!
515+
const body = World.physicsSystem.getBody(bodyId)
516+
if (!body) return
515517
const transform = convertJoltMat44ToThreeMatrix4(body.GetWorldTransform())
516518
this.updateNodeParts(rn, transform)
517519

fission/src/systems/physics/PhysicsSystem.ts

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -964,12 +964,22 @@ class PhysicsSystem extends WorldSystem {
964964
const partDefinition =
965965
parser.assembly.data!.parts!.partDefinitions![partInstance.partDefinitionReference!]!
966966

967+
const debugLabel = {
968+
rn: rn.id,
969+
partId,
970+
defRef: partInstance.partDefinitionReference,
971+
name: (partDefinition as any).name ?? (partInstance as any).name ?? "(unnamed)",
972+
}
973+
967974
const partShapeResult = rn.isDynamic
968975
? this.createConvexShapeSettingsFromPart(partDefinition)
969-
: this.createConcaveShapeSettingsFromPart(partDefinition)
976+
: this.createConcaveShapeSettingsFromPart(partDefinition, debugLabel)
970977
// const partShapeResult = this.CreateConvexShapeSettingsFromPart(partDefinition)
971978

972-
if (!partShapeResult) return
979+
if (!partShapeResult) {
980+
console.warn("Skipping collider (no valid shape settings)", debugLabel)
981+
return
982+
}
973983

974984
const [shapeSettings, partMin, partMax] = partShapeResult
975985

@@ -1039,7 +1049,11 @@ class PhysicsSystem extends WorldSystem {
10391049
const shapeResult = compoundShapeSettings.Create()
10401050

10411051
if (!shapeResult.IsValid || shapeResult.HasError()) {
1052+
// Grounds for a crash
10421053
console.error(`Failed to create shape for RigidNode ${rn.id}\n${shapeResult.GetError().c_str()}`)
1054+
1055+
JOLT.destroy(compoundShapeSettings)
1056+
return
10431057
}
10441058

10451059
const shape = shapeResult.Get()
@@ -1136,7 +1150,8 @@ class PhysicsSystem extends WorldSystem {
11361150
* @returns If successful, the created convex hull shape settings from the given Part Definition.
11371151
*/
11381152
private createConcaveShapeSettingsFromPart(
1139-
partDefinition: mirabuf.IPartDefinition
1153+
partDefinition: mirabuf.IPartDefinition,
1154+
debugLabel?: any
11401155
): [Jolt.ShapeSettings, Jolt.Vec3, Jolt.Vec3] | undefined {
11411156
const settings = new JOLT.MeshShapeSettings()
11421157

@@ -1151,32 +1166,72 @@ class PhysicsSystem extends WorldSystem {
11511166
const min = new JOLT.Vec3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY)
11521167
const max = new JOLT.Vec3(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY)
11531168

1169+
let maxIndex = -1
11541170
partDefinition.bodies!.forEach(body => {
11551171
const vertArr = body.triangleMesh?.mesh?.verts
11561172
const indexArr = body.triangleMesh?.mesh?.indices
11571173
if (!vertArr || !indexArr) return
11581174

1175+
// Basic index sanity: must be triangle list
1176+
if (indexArr.length < 3 || indexArr.length % 3 !== 0) {
1177+
// Defer logging to caller with context
1178+
return
1179+
}
1180+
11591181
for (let i = 0; i < vertArr.length; i += 3) {
11601182
const vert = convertMirabufFloatToArrJoltFloat3(vertArr, i)
11611183
settings.mTriangleVertices.push_back(vert)
11621184
this.updateMinMaxBounds(new JOLT.Vec3(vert), min, max)
11631185
JOLT.destroy(vert)
11641186
}
11651187
for (let i = 0; i < indexArr.length; i += 3) {
1166-
settings.mIndexedTriangles.push_back(
1167-
new JOLT.IndexedTriangle(indexArr.at(i)!, indexArr.at(i + 1)!, indexArr.at(i + 2)!, 0)
1168-
)
1188+
const a = indexArr.at(i)!
1189+
const b = indexArr.at(i + 1)!
1190+
const c = indexArr.at(i + 2)!
1191+
if (a > maxIndex) maxIndex = a
1192+
if (b > maxIndex) maxIndex = b
1193+
if (c > maxIndex) maxIndex = c
1194+
settings.mIndexedTriangles.push_back(new JOLT.IndexedTriangle(a, b, c, 0))
11691195
}
11701196
})
11711197

1172-
if (settings.mTriangleVertices.size() < 4) {
1198+
const vertCount = settings.mTriangleVertices.size()
1199+
const triCountBeforeSanitize = settings.mIndexedTriangles.size()
1200+
1201+
// Vertex count must support at least one triangle; also ensure indices reference existing vertices
1202+
if (vertCount < 3 || triCountBeforeSanitize === 0 || maxIndex >= vertCount) {
1203+
if (debugLabel) {
1204+
console.warn(
1205+
"Concave collider invalid (no triangles or bad indices)",
1206+
{ ...debugLabel, vertCount, triCount: triCountBeforeSanitize, maxIndex }
1207+
)
1208+
}
1209+
11731210
JOLT.destroy(settings)
11741211
JOLT.destroy(min)
11751212
JOLT.destroy(max)
1213+
// TODO: This could be a fatal error returning here
11761214
return
11771215
}
11781216

1217+
// Sanitize may drop degenerates; verify at least one triangle remains
11791218
settings.Sanitize()
1219+
const triCount = settings.mIndexedTriangles.size()
1220+
if (triCount === 0) {
1221+
if (debugLabel) {
1222+
console.warn(
1223+
"Concave collider sanitized to zero triangles (degenerate)",
1224+
{ ...debugLabel, vertCount, triCountBeforeSanitize }
1225+
)
1226+
}
1227+
1228+
JOLT.destroy(settings)
1229+
JOLT.destroy(min)
1230+
JOLT.destroy(max)
1231+
// TODO: This could be a fatal error returning here
1232+
return
1233+
}
1234+
11801235
return [settings, min, max]
11811236
}
11821237

0 commit comments

Comments
 (0)