@@ -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