{"record":{"id":"cda8726753718d94","repo":"stride3d/stride","slug":"invalid-state-when-computing-tetrahedron","errorCode":null,"errorMessage":"Invalid state when computing tetrahedron","messagePattern":"Invalid state when computing tetrahedron","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Rendering/Rendering/LightProbes/BowyerWatsonTetrahedralization.cs","lineNumber":732,"sourceCode":"\n                    Vector3 normal;\n                    switch (unused)\n                    {\n                        case 0:\n                            normal = new Vector3(1.0f, 1.0f, 1.0f);\n                            normal.Normalize();\n                            break;\n                        case 1:\n                            normal = -Vector3.UnitZ;\n                            break;\n                        case 2:\n                            normal = -Vector3.UnitY;\n                            break;\n                        case 3:\n                            normal = -Vector3.UnitX;\n                            break;\n                        default:\n                            throw new InvalidOperationException(\"Invalid state when computing tetrahedron\");\n                    }\n\n                    var plane = new Plane(points[infinityIndices[0]], normal);\n                    var result = Predicates.insphere(ref points[tetrahedronPointer->Vertices[0]], ref points[tetrahedronPointer->Vertices[1]], ref points[tetrahedronPointer->Vertices[2]], ref points[tetrahedronPointer->Vertices[3]], ref p);\n                    return CollisionHelper.DistancePlanePoint(ref plane, ref p) > 0.0f;\n                }\n                else if (infinityCount == 2)\n                {\n                    // Build a plane that contains both points not at infinity, and that is also parallel to the line formed by the two points at \"infinity\"\n                    var infinitePerpendicularLine = points[infinityIndices[3]] - points[infinityIndices[2]];\n                    var plane = new Plane(points[infinityIndices[0]], points[infinityIndices[1]], points[infinityIndices[0]] + infinitePerpendicularLine);\n                    var result = Predicates.insphere(ref points[tetrahedronPointer->Vertices[0]], ref points[tetrahedronPointer->Vertices[1]], ref points[tetrahedronPointer->Vertices[2]], ref points[tetrahedronPointer->Vertices[3]], ref p);\n                    return CollisionHelper.DistancePlanePoint(ref plane, ref p) > 0.0f;\n                }\n                else if (infinityCount == 1)\n                {\n                    // 1 from super tetrahedra out of 4\n                    // Find which one is used","sourceCodeStart":714,"sourceCodeEnd":750,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Rendering/Rendering/LightProbes/BowyerWatsonTetrahedralization.cs#L714-L750","documentation":"BowyerWatsonTetrahedralization computes a tetrahedralization for light probe placement. While checking whether a point is inside a tetrahedron's circumsphere, it builds a plane for one of the four faces using a switch over face indices; if the face index is outside 0-3 the internal face-index table is corrupt, so the library throws InvalidOperationException rather than produce a wrong tetrahedralization.","triggerScenarios":"Internal state corruption in the tetrahedralization: the infinityIndices / face-index mapping yields a value outside 0-3 when computing the bounding planes of the super-tetrahedron during InSphere checks. Only reachable via BowyerWatsonTetrahedralization with degenerate or duplicate probe points that corrupt the face bookkeeping.","commonSituations":"Custom light probe setups with coincident or collinear probe points, or a modified/patched copy of the algorithm breaking the face-index invariants; not normally reachable through supported public APIs.","solutions":["Check for duplicate or exactly collinear light probe point coordinates in the input set and remove/offset them","Verify no custom modifications to BowyerWatsonTetrahedralization broke the face-index table (indices 0-3)","Capture the input point set and report a bug to Stride with a minimal reproducible probe layout","Update Stride to the latest version in case the tetrahedralization bug was fixed upstream"],"exampleFix":"// before: duplicate probe positions collapse face bookkeeping\nvar points = new[] { p0, p1, p1, p2 };\n// after: deduplicate points before tetrahedralization\nvar points = probePositions.Distinct().ToArray();","handlingStrategy":"try-catch","validationCode":"// deduplicate and sanity-check probe points before tetrahedralization\nvar distinct = probePositions.Distinct().ToList();\nif (distinct.Count < 4) throw new ArgumentException(\"Need at least 4 distinct probe points\");","typeGuard":"bool IsValidProbeSet(IReadOnlyList<Vector3> pts) =>\n    pts.Distinct().Count() == pts.Count && pts.Count >= 4;","tryCatchPattern":"try { var tetra = new BowyerWatsonTetrahedralization(points); ... }\ncatch (InvalidOperationException ex)\n{\n    logger.LogError(ex, \"Tetrahedralization failed; check probe point layout\");\n    // fall back to grid-based probe placement\n}","preventionTips":["Ensure probe points are distinct and not exactly collinear/coplanar in degenerate ways","Do not modify the internal face-index logic of the algorithm","Keep Stride updated for fixed numerical robustness in Predicates"],"tags":["lightprobes","tetrahedralization","invalid-state","geometry"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}