@woosh/meep-engine 2.168.0 → 2.169.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/bundle-worker-image-decoder.js +1 -1
- package/package.json +1 -1
- package/src/REVIEW_2026_08_06/adv-core.md +511 -0
- package/src/REVIEW_2026_08_06/adv-gfx.md +480 -0
- package/src/REVIEW_2026_08_06/adv-view.md +446 -0
- package/src/REVIEW_2026_08_06/api-core.md +296 -0
- package/src/REVIEW_2026_08_06/api-engine.md +195 -0
- package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -0
- package/src/REVIEW_2026_08_06/core-binary.md +348 -0
- package/src/REVIEW_2026_08_06/core-collection.md +376 -0
- package/src/REVIEW_2026_08_06/core-math.md +221 -0
- package/src/REVIEW_2026_08_06/core-process.md +266 -0
- package/src/REVIEW_2026_08_06/core-science.md +223 -0
- package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -0
- package/src/REVIEW_2026_08_06/engine-animation.md +167 -0
- package/src/REVIEW_2026_08_06/engine-asset.md +166 -0
- package/src/REVIEW_2026_08_06/engine-ecs.md +920 -0
- package/src/REVIEW_2026_08_06/engine-input.md +197 -0
- package/src/REVIEW_2026_08_06/engine-misc.md +248 -0
- package/src/REVIEW_2026_08_06/engine-terrain.md +52 -0
- package/src/REVIEW_2026_08_06/generation.md +176 -0
- package/src/REVIEW_2026_08_06/geom-2d.md +434 -0
- package/src/REVIEW_2026_08_06/geom-3d.md +117 -0
- package/src/REVIEW_2026_08_06/gfx-gi.md +143 -0
- package/src/REVIEW_2026_08_06/gfx-render.md +740 -0
- package/src/REVIEW_2026_08_06/gfx-texture.md +690 -0
- package/src/REVIEW_2026_08_06/prior-criticals.md +49 -0
- package/src/REVIEW_2026_08_06/prior-highs.md +138 -0
- package/src/REVIEW_2026_08_06/test-gaps.md +364 -0
- package/src/REVIEW_2026_08_06/view.md +667 -0
- package/src/REVIEW_2026_08_06.md +571 -0
- package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
- package/src/core/binary/BinaryBuffer.js +12 -1
- package/src/core/binary/BitImage2.d.ts +5 -1
- package/src/core/binary/BitImage2.d.ts.map +1 -1
- package/src/core/binary/BitImage2.js +5 -1
- package/src/core/bvh8/build/NodeProxy.d.ts.map +1 -1
- package/src/core/bvh8/build/NodeProxy.js +314 -308
- package/src/core/collection/list/List.d.ts +15 -0
- package/src/core/collection/list/List.d.ts.map +1 -1
- package/src/core/collection/list/List.js +34 -0
- package/src/core/collection/list/SortedListProjection.d.ts.map +1 -1
- package/src/core/collection/list/SortedListProjection.js +4 -1
- package/src/core/collection/map/BiMap.d.ts +25 -2
- package/src/core/collection/map/BiMap.d.ts.map +1 -1
- package/src/core/collection/map/BiMap.js +57 -3
- package/src/core/debug/matchers/IsAnything.d.ts.map +1 -1
- package/src/core/debug/matchers/IsAnything.js +5 -1
- package/src/core/events/signal/Signal.d.ts.map +1 -1
- package/src/core/events/signal/Signal.js +3 -1
- package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -0
- package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts +31 -0
- package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -0
- package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts +24 -2
- package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts.map +1 -1
- package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -34
- package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts +28 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts +40 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -0
- package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts +28 -0
- package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts +6 -3
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts.map +1 -1
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +26 -13
- package/src/core/geom/2d/triangle/tri2_signed_area.d.ts +17 -1
- package/src/core/geom/2d/triangle/tri2_signed_area.d.ts.map +1 -1
- package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -23
- package/src/core/geom/2d/v2_morton_encode.d.ts +20 -0
- package/src/core/geom/2d/v2_morton_encode.d.ts.map +1 -0
- package/src/core/geom/2d/v2_morton_encode.js +23 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts.map +1 -1
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +4 -1
- package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts +27 -0
- package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts.map +1 -0
- package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -0
- package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts +34 -0
- package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts.map +1 -0
- package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -0
- package/src/core/geom/3d/quaternion/quat3_multiply.d.ts +8 -2
- package/src/core/geom/3d/quaternion/quat3_multiply.d.ts.map +1 -1
- package/src/core/geom/3d/quaternion/quat3_multiply.js +8 -2
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.js +32 -2
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts +23 -6
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -124
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts +17 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts +20 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.js +40 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts +19 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.js +34 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts +22 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.js +37 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts +87 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -0
- package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts +32 -0
- package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts.map +1 -1
- package/src/core/geom/3d/triangle/tri3_compute_signed_volume.js +66 -7
- package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts +22 -1
- package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts.map +1 -1
- package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.js +83 -38
- package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -0
- package/src/core/geom/vec3/v3_cotangent.d.ts +6 -2
- package/src/core/geom/vec3/v3_cotangent.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_cotangent.js +6 -2
- package/src/core/geom/vec3/v3_cross.d.ts +6 -2
- package/src/core/geom/vec3/v3_cross.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_cross.js +6 -2
- package/src/core/geom/vec3/v3_multiply.d.ts +6 -2
- package/src/core/geom/vec3/v3_multiply.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_multiply.js +6 -2
- package/src/core/geom/vec3/v3_subtract.d.ts +6 -2
- package/src/core/geom/vec3/v3_subtract.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_subtract.js +6 -2
- package/src/core/localization/Localization.js +1 -1
- package/src/core/math/random/randomSeed.d.ts +13 -0
- package/src/core/math/random/randomSeed.d.ts.map +1 -0
- package/src/core/math/random/randomSeed.js +16 -0
- package/src/core/math/spline/spline3_hermite_apply_transform.d.ts +50 -0
- package/src/core/math/spline/spline3_hermite_apply_transform.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -0
- package/src/core/math/spline/spline3_hermite_reverse.d.ts +34 -0
- package/src/core/math/spline/spline3_hermite_reverse.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_reverse.js +49 -0
- package/src/core/math/statistics/hammersley_sequence.d.ts +17 -4
- package/src/core/math/statistics/hammersley_sequence.d.ts.map +1 -1
- package/src/core/math/statistics/hammersley_sequence.js +25 -16
- package/src/core/process/Future.d.ts.map +1 -1
- package/src/core/process/Future.js +12 -0
- package/src/core/process/PromiseWatcher.d.ts.map +1 -1
- package/src/core/process/PromiseWatcher.js +9 -2
- package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
- package/src/core/process/executor/ConcurrentExecutor.js +12 -2
- package/src/core/process/worker/WorkerProxy.d.ts.map +1 -1
- package/src/core/process/worker/WorkerProxy.js +5 -2
- package/src/core/process/worker/extractTransferables.d.ts.map +1 -1
- package/src/core/process/worker/extractTransferables.js +4 -1
- package/src/engine/Engine.d.ts +12 -12
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +149 -10
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +4 -1
- package/src/engine/asset/loaders/ArrayBufferLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/ArrayBufferLoader.js +7 -0
- package/src/engine/ecs/speaker/lines/sets/LineSetDescription.d.ts.map +1 -1
- package/src/engine/ecs/speaker/lines/sets/LineSetDescription.js +3 -1
- package/src/engine/ecs/terrain/ecs/TerrainSystem.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/TerrainSystem.js +4 -1
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts +29 -0
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +84 -23
- package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -0
- package/src/engine/graphics/GraphicsEngine.d.ts +56 -7
- package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics/GraphicsEngine.js +196 -24
- package/src/engine/graphics/context/WebGLContextFailureReason.d.ts +9 -0
- package/src/engine/graphics/context/WebGLContextFailureReason.d.ts.map +1 -0
- package/src/engine/graphics/context/WebGLContextFailureReason.js +17 -0
- package/src/engine/graphics/context/WebGLContextMonitor.d.ts +106 -0
- package/src/engine/graphics/context/WebGLContextMonitor.d.ts.map +1 -0
- package/src/engine/graphics/context/WebGLContextMonitor.js +341 -0
- package/src/engine/graphics/context/WebGLContextState.d.ts +14 -0
- package/src/engine/graphics/context/WebGLContextState.d.ts.map +1 -0
- package/src/engine/graphics/context/WebGLContextState.js +24 -0
- package/src/engine/graphics/context/testWebGLContextLoss.d.ts +2 -0
- package/src/engine/graphics/context/testWebGLContextLoss.d.ts.map +1 -0
- package/src/engine/graphics/context/testWebGLContextLoss.js +696 -0
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -32
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts +14 -0
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.js +41 -0
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +5 -0
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts +5 -1
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2D.js +15 -0
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +2 -1
- package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +4 -1
- package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3D.js +488 -476
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.js +280 -253
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +3 -2
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +3 -1
- package/src/engine/graphics/geometry/computeMeshSurfaceArea.js +1 -1
- package/src/engine/graphics/load_and_set_cubemap_v0.d.ts +5 -0
- package/src/engine/graphics/load_and_set_cubemap_v0.d.ts.map +1 -1
- package/src/engine/graphics/load_and_set_cubemap_v0.js +26 -21
- package/src/engine/graphics/particles/particular/group/ParticleGroup.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/group/ParticleGroup.js +19 -8
- package/src/engine/graphics/particles/particular/group/optimizeCommandQueue.js +1 -1
- package/src/engine/graphics/texture/atlas/AtlasLookupTexture.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/AtlasLookupTexture.js +10 -3
- package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.js +4 -1
- package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +11 -0
- package/src/engine/graphics/texture/cubemap/load_environment_map.d.ts.map +1 -1
- package/src/engine/graphics/texture/cubemap/load_environment_map.js +5 -2
- package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.js +26 -18
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts +15 -2
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.js +29 -3
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts +11 -1
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +158 -171
- package/src/engine/graphics/texture/sampler/sampler2d_paint.js +1 -1
- package/src/engine/graphics/texture/sampler/util/bitSet2Sampler2D.js +2 -2
- package/src/engine/input/ecs/util/TopDownCameraControllerHelper.d.ts.map +1 -1
- package/src/engine/input/ecs/util/TopDownCameraControllerHelper.js +10 -3
- package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts +14 -0
- package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts.map +1 -0
- package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.js +38 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +433 -425
- package/src/engine/physics/constraint/solve_constraints.d.ts +4 -1
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +38 -13
- package/src/engine/physics/contact/ManifoldStore.d.ts +15 -3
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
- package/src/engine/physics/contact/ManifoldStore.js +15 -3
- package/src/engine/physics/ecs/Joint.d.ts +7 -4
- package/src/engine/physics/ecs/Joint.d.ts.map +1 -1
- package/src/engine/physics/ecs/Joint.js +7 -4
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +14 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +16 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +15 -7
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/convex_convex_manifold.js +33 -10
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts +6 -2
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_concave.js +6 -2
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +6 -2
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_hit.js +6 -2
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +11 -4
- package/src/engine/save/storage/IndexedDBStorage.d.ts.map +1 -1
- package/src/engine/save/storage/IndexedDBStorage.js +21 -3
- package/src/engine/simulation/Ticker.d.ts +12 -0
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +18 -0
- package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
- package/src/engine/sound/simulation/AcousticSimulator.js +9 -1
- package/src/engine/sound/simulation/core/VolumeField.d.ts +6 -2
- package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/VolumeField.js +6 -2
- package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts +6 -2
- package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/AcousticProbeField.js +6 -2
- package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts +6 -2
- package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +6 -2
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts +3 -1
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +3 -1
- package/src/engine/ui/GUIEngine.d.ts.map +1 -1
- package/src/engine/ui/GUIEngine.js +8 -1
- package/src/generation/theme/TerrainTheme.d.ts.map +1 -1
- package/src/generation/theme/TerrainTheme.js +2 -1
- package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
- package/src/generation/theme/ThemeEngine.js +6 -5
- package/src/view/ViewGroup.d.ts.map +1 -1
- package/src/view/ViewGroup.js +9 -7
- package/src/view/graphics/WebGLContextFailureView.d.ts +19 -0
- package/src/view/graphics/WebGLContextFailureView.d.ts.map +1 -0
- package/src/view/graphics/WebGLContextFailureView.js +76 -0
- package/src/view/minimap/Minimap.d.ts +8 -0
- package/src/view/minimap/Minimap.d.ts.map +1 -1
- package/src/view/minimap/Minimap.js +16 -3
- package/src/view/minimap/dom/MinimapMarkerView.d.ts.map +1 -1
- package/src/view/minimap/dom/MinimapMarkerView.js +3 -1
|
@@ -113,10 +113,34 @@ export class ConvexHullShape3D extends AbstractShape3D {
|
|
|
113
113
|
const b = this.__bbox;
|
|
114
114
|
b[0] = mnx; b[1] = mny; b[2] = mnz; b[3] = mxx; b[4] = mxy; b[5] = mxz;
|
|
115
115
|
|
|
116
|
+
// Volume is accumulated about the hull's own bbox centre, not the
|
|
117
|
+
// origin. Σ a·(b×c) is translation invariant over a closed surface --
|
|
118
|
+
// shifting `a` by a constant r changes the sum by r·Σn, and the face
|
|
119
|
+
// area vectors of a closed surface sum to zero -- so the apex may be
|
|
120
|
+
// moved freely, and moving it onto the hull is what keeps the terms on
|
|
121
|
+
// the scale of the hull instead of on the scale of its distance from
|
|
122
|
+
// the origin. Anchored at the origin, a hull sitting 1e6 away produced
|
|
123
|
+
// terms around 1e18 that had to cancel down to its volume, and the
|
|
124
|
+
// reported volume drifted by ~7e-4 relative for a hull whose vertices
|
|
125
|
+
// were stored exactly.
|
|
126
|
+
//
|
|
127
|
+
// Σn = 0 needs the surface to be closed and consistently wound, which
|
|
128
|
+
// `from` does not check. For a surface that is not -- an open cap, a
|
|
129
|
+
// flipped or duplicated face -- this reports a different number than
|
|
130
|
+
// anchoring at the origin did. Both are meaningless for such input, but
|
|
131
|
+
// note the old one was meaningless in a more flattering way: a face
|
|
132
|
+
// touching the origin contributed nothing, so a broken hull could still
|
|
133
|
+
// read a plausible 1.0 at the origin and something else entirely once
|
|
134
|
+
// translated. This number is at least a property of the surface rather
|
|
135
|
+
// than of where it sits.
|
|
136
|
+
const ox = (mnx + mxx) * 0.5;
|
|
137
|
+
const oy = (mny + mxy) * 0.5;
|
|
138
|
+
const oz = (mnz + mxz) * 0.5;
|
|
139
|
+
|
|
116
140
|
const tri = idx.length / 3;
|
|
117
141
|
const planes = new Float64Array(tri * 4);
|
|
118
142
|
let area = 0;
|
|
119
|
-
let vol6 = 0; // 6× the signed volume (Σ a·
|
|
143
|
+
let vol6 = 0; // 6× the signed volume (Σ (a − o)·n over outward faces)
|
|
120
144
|
for (let f = 0; f < tri; f++) {
|
|
121
145
|
const ia = idx[f * 3] * 3, ib = idx[f * 3 + 1] * 3, ic = idx[f * 3 + 2] * 3;
|
|
122
146
|
const ax = v[ia], ay = v[ia + 1], az = v[ia + 2];
|
|
@@ -130,7 +154,13 @@ export class ConvexHullShape3D extends AbstractShape3D {
|
|
|
130
154
|
let nz = e1x * e2y - e1y * e2x;
|
|
131
155
|
const len = Math.sqrt(nx * nx + ny * ny + nz * nz) || 1;
|
|
132
156
|
area += 0.5 * len;
|
|
133
|
-
|
|
157
|
+
// Two rewrites, both exact, and together they remove every product
|
|
158
|
+
// of absolute coordinates:
|
|
159
|
+
// a·(b × c) === a·((b − a) × (c − a)), since a·(b × a) and
|
|
160
|
+
// a·(a × c) are both zero -- so the normal already computed above
|
|
161
|
+
// can be reused in place of the b × c cross product;
|
|
162
|
+
// Σ a·n === Σ (a − o)·n over a closed surface, since Σ n = 0.
|
|
163
|
+
vol6 += (ax - ox) * nx + (ay - oy) * ny + (az - oz) * nz;
|
|
134
164
|
|
|
135
165
|
nx /= len; ny /= len; nz /= len;
|
|
136
166
|
const o = f * 4;
|
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Split one face of a {@link BinaryTopology} into triangles, in place.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Handles any simple polygon, convex or not: the corner order is projected onto
|
|
5
|
+
* the plane of the face's own Newell normal and triangulated by
|
|
6
|
+
* {@link polygon3_triangulate}, whose decisions are exact. The resulting ear
|
|
7
|
+
* sequence is then replayed as topology surgery, so existing corners keep their
|
|
8
|
+
* identity (and any per-loop data) and only the diagonals are new. Each new face
|
|
9
|
+
* inherits the original's stored normal.
|
|
5
10
|
*
|
|
6
|
-
*
|
|
11
|
+
* Superseded the previous fan-from-the-first-corner implementation, which was
|
|
12
|
+
* correct only for convex faces and produced silently overlapping triangles for
|
|
13
|
+
* anything else.
|
|
14
|
+
*
|
|
15
|
+
* Nothing is changed, and `1` is returned, when the face is already a triangle,
|
|
16
|
+
* has no area (so no plane to project onto), or projects to a self-intersecting
|
|
17
|
+
* outline -- which is a non-planar or otherwise malformed face, and cannot be cut
|
|
18
|
+
* into ears at all. Leaving it whole is the honest outcome; half-cutting it would
|
|
19
|
+
* corrupt the mesh.
|
|
7
20
|
*
|
|
8
21
|
* @param {BinaryTopology} mesh
|
|
9
|
-
* @param {number} face
|
|
10
|
-
* @
|
|
22
|
+
* @param {number} face
|
|
23
|
+
* @returns {number} how many faces the input face became: `1` when it was left
|
|
24
|
+
* untouched, otherwise the number of triangles it was split into
|
|
25
|
+
*
|
|
26
|
+
* @author Alex Goldring
|
|
27
|
+
* @copyright Company Named Limited (c) 2026
|
|
11
28
|
*/
|
|
12
|
-
export function bt_face_triangulate(mesh: BinaryTopology, face: number):
|
|
29
|
+
export function bt_face_triangulate(mesh: BinaryTopology, face: number): number;
|
|
13
30
|
//# sourceMappingURL=bt_face_triangulate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bt_face_triangulate.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bt_face_triangulate.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js"],"names":[],"mappings":"AAqKA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,gEAPW,MAAM,GACJ,MAAM,CAgFlB"}
|
|
@@ -1,124 +1,268 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
1
|
+
import { polygon3_compute_normal } from "../../../../../polygon/polygon3_compute_normal.js";
|
|
2
|
+
import { polygon3_triangulate } from "../../../../../polygon/polygon3_triangulate.js";
|
|
3
|
+
import { NULL_POINTER } from "../../BinaryTopology.js";
|
|
4
|
+
import { bt_radial_loop_add } from "../bt_radial_loop_add.js";
|
|
5
|
+
import { bt_edge_create } from "../edge/bt_edge_create.js";
|
|
6
|
+
|
|
7
|
+
// Per-call scratch, grown on demand. Faces are small, so these stay tiny in
|
|
8
|
+
// practice; module-static so triangulating a whole mesh allocates nothing.
|
|
9
|
+
let _loops = new Uint32Array(0);
|
|
10
|
+
let _positions = new Float64Array(0);
|
|
11
|
+
let _triangles = new Uint32Array(0);
|
|
12
|
+
let _ring_next = new Uint32Array(0);
|
|
13
|
+
let _ring_prev = new Uint32Array(0);
|
|
14
|
+
|
|
15
|
+
const _contour_ends = new Uint32Array(1);
|
|
16
|
+
const _normal = new Float64Array(3);
|
|
17
|
+
const _stored_normal = new Float32Array(3);
|
|
18
|
+
const _coordinate = new Float32Array(3);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {number} corner_count
|
|
22
|
+
*/
|
|
23
|
+
function ensure_capacity(corner_count) {
|
|
24
|
+
if (_loops.length >= corner_count) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
_loops = new Uint32Array(corner_count);
|
|
29
|
+
_positions = new Float64Array(corner_count * 3);
|
|
30
|
+
_triangles = new Uint32Array(Math.max(0, corner_count - 2) * 3);
|
|
31
|
+
_ring_next = new Uint32Array(corner_count);
|
|
32
|
+
_ring_prev = new Uint32Array(corner_count);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Cut the triangle `(prev(l_ear), l_ear, next(l_ear))` off `face` as a new face,
|
|
37
|
+
* leaving `face` one corner smaller.
|
|
38
|
+
*
|
|
39
|
+
* The two existing corners move to the new face and two fresh loops are created:
|
|
40
|
+
* one closing the triangle at the far vertex, one continuing the shrunken polygon
|
|
41
|
+
* at the near vertex. Both are attached to the new diagonal edge's radial cycle.
|
|
42
|
+
*
|
|
43
|
+
* @param {BinaryTopology} mesh
|
|
44
|
+
* @param {number} face
|
|
45
|
+
* @param {number} l_ear the corner being cut away
|
|
46
|
+
* @param {Float32Array} normal applied to the new face
|
|
47
|
+
* @returns {number} the replacement corner the shrunken polygon now has at the
|
|
48
|
+
* ear's predecessor vertex -- the old one moved to the new triangle, so any
|
|
49
|
+
* caller holding it must swap in this one
|
|
50
|
+
*/
|
|
51
|
+
function cut_ear(mesh, face, l_ear, normal) {
|
|
52
|
+
const l_prev = mesh.loop_read_prev(l_ear);
|
|
53
|
+
const l_next = mesh.loop_read_next(l_ear);
|
|
54
|
+
|
|
55
|
+
const v_anchor = mesh.loop_read_vertex(l_prev);
|
|
56
|
+
const v_target = mesh.loop_read_vertex(l_next);
|
|
57
|
+
|
|
58
|
+
// handles allocation and vertex-disk linking for the diagonal
|
|
59
|
+
const e_new = bt_edge_create(mesh, v_anchor, v_target);
|
|
60
|
+
|
|
61
|
+
const f_new = mesh.faces.allocate();
|
|
62
|
+
const l_tri = mesh.loop_create(); // closes the triangle, at v_target
|
|
63
|
+
const l_poly = mesh.loop_create(); // continues the polygon, at v_anchor
|
|
64
|
+
|
|
65
|
+
mesh.loop_write_vertex(l_tri, v_target);
|
|
66
|
+
mesh.loop_write_face(l_tri, f_new);
|
|
67
|
+
|
|
68
|
+
mesh.loop_write_vertex(l_poly, v_anchor);
|
|
69
|
+
mesh.loop_write_face(l_poly, face);
|
|
70
|
+
|
|
71
|
+
bt_radial_loop_add(mesh, l_tri, e_new);
|
|
72
|
+
bt_radial_loop_add(mesh, l_poly, e_new);
|
|
73
|
+
|
|
74
|
+
const l_prev_prev = mesh.loop_read_prev(l_prev);
|
|
75
|
+
|
|
76
|
+
mesh.loop_write_face(l_prev, f_new);
|
|
77
|
+
mesh.loop_write_face(l_ear, f_new);
|
|
78
|
+
|
|
79
|
+
// triangle: l_prev -> l_ear -> l_tri
|
|
80
|
+
mesh.loop_write_next(l_prev, l_ear);
|
|
81
|
+
mesh.loop_write_prev(l_prev, l_tri);
|
|
82
|
+
|
|
83
|
+
mesh.loop_write_next(l_ear, l_tri);
|
|
84
|
+
mesh.loop_write_prev(l_ear, l_prev);
|
|
85
|
+
|
|
86
|
+
mesh.loop_write_next(l_tri, l_prev);
|
|
87
|
+
mesh.loop_write_prev(l_tri, l_ear);
|
|
88
|
+
|
|
89
|
+
mesh.face_write_loop(f_new, l_prev);
|
|
90
|
+
mesh.face_write_normal(f_new, normal, 0);
|
|
91
|
+
|
|
92
|
+
// remaining polygon: l_prev_prev -> l_poly -> l_next
|
|
93
|
+
mesh.loop_write_next(l_prev_prev, l_poly);
|
|
94
|
+
|
|
95
|
+
mesh.loop_write_prev(l_poly, l_prev_prev);
|
|
96
|
+
mesh.loop_write_next(l_poly, l_next);
|
|
97
|
+
|
|
98
|
+
mesh.loop_write_prev(l_next, l_poly);
|
|
99
|
+
|
|
100
|
+
mesh.face_write_loop(face, l_poly);
|
|
101
|
+
|
|
102
|
+
return l_poly;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Reset the corner index ring to `0 -> 1 -> ... -> corner_count - 1 -> 0`, the
|
|
107
|
+
* order the corners were collected in.
|
|
108
|
+
*
|
|
109
|
+
* @param {number} corner_count
|
|
110
|
+
*/
|
|
111
|
+
function reset_ring(corner_count) {
|
|
112
|
+
for (let i = 0; i < corner_count; i++) {
|
|
113
|
+
_ring_next[i] = (i + 1) % corner_count;
|
|
114
|
+
_ring_prev[i] = (i + corner_count - 1) % corner_count;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Remove index `i` from the corner ring.
|
|
120
|
+
*
|
|
121
|
+
* @param {number} i
|
|
122
|
+
*/
|
|
123
|
+
function unlink_ring(i) {
|
|
124
|
+
_ring_next[_ring_prev[i]] = _ring_next[i];
|
|
125
|
+
_ring_prev[_ring_next[i]] = _ring_prev[i];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Replay the emitted triangle list against a plain index ring without touching the
|
|
130
|
+
* mesh, checking that every triple is an ear of the ring at the moment it is
|
|
131
|
+
* reached. Only then is it safe to perform the same sequence as topology surgery.
|
|
132
|
+
*
|
|
133
|
+
* Ear clipping emits exactly this sequence for a simple polygon. Its recovery
|
|
134
|
+
* passes, which run for a self-intersecting projection, do not -- and half-applying
|
|
135
|
+
* those would leave the mesh structurally broken rather than merely untriangulated.
|
|
136
|
+
*
|
|
137
|
+
* @param {number} corner_count
|
|
138
|
+
* @param {number} triangle_count
|
|
139
|
+
* @returns {boolean}
|
|
140
|
+
*/
|
|
141
|
+
function is_ear_sequence(corner_count, triangle_count) {
|
|
142
|
+
if (triangle_count !== corner_count - 2) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
reset_ring(corner_count);
|
|
147
|
+
|
|
148
|
+
for (let t = 0; t < triangle_count; t++) {
|
|
149
|
+
const a = _triangles[t * 3];
|
|
150
|
+
const b = _triangles[t * 3 + 1];
|
|
151
|
+
const c = _triangles[t * 3 + 2];
|
|
152
|
+
|
|
153
|
+
const forward = _ring_prev[b] === a && _ring_next[b] === c;
|
|
154
|
+
const backward = _ring_prev[b] === c && _ring_next[b] === a;
|
|
155
|
+
|
|
156
|
+
if (!forward && !backward) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
unlink_ring(b);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Split one face of a {@link BinaryTopology} into triangles, in place.
|
|
168
|
+
*
|
|
169
|
+
* Handles any simple polygon, convex or not: the corner order is projected onto
|
|
170
|
+
* the plane of the face's own Newell normal and triangulated by
|
|
171
|
+
* {@link polygon3_triangulate}, whose decisions are exact. The resulting ear
|
|
172
|
+
* sequence is then replayed as topology surgery, so existing corners keep their
|
|
173
|
+
* identity (and any per-loop data) and only the diagonals are new. Each new face
|
|
174
|
+
* inherits the original's stored normal.
|
|
175
|
+
*
|
|
176
|
+
* Superseded the previous fan-from-the-first-corner implementation, which was
|
|
177
|
+
* correct only for convex faces and produced silently overlapping triangles for
|
|
178
|
+
* anything else.
|
|
179
|
+
*
|
|
180
|
+
* Nothing is changed, and `1` is returned, when the face is already a triangle,
|
|
181
|
+
* has no area (so no plane to project onto), or projects to a self-intersecting
|
|
182
|
+
* outline -- which is a non-planar or otherwise malformed face, and cannot be cut
|
|
183
|
+
* into ears at all. Leaving it whole is the honest outcome; half-cutting it would
|
|
184
|
+
* corrupt the mesh.
|
|
185
|
+
*
|
|
186
|
+
* @param {BinaryTopology} mesh
|
|
187
|
+
* @param {number} face
|
|
188
|
+
* @returns {number} how many faces the input face became: `1` when it was left
|
|
189
|
+
* untouched, otherwise the number of triangles it was split into
|
|
190
|
+
*
|
|
191
|
+
* @author Alex Goldring
|
|
192
|
+
* @copyright Company Named Limited (c) 2026
|
|
193
|
+
*/
|
|
194
|
+
export function bt_face_triangulate(mesh, face) {
|
|
195
|
+
const first_loop = mesh.face_read_loop(face);
|
|
196
|
+
|
|
197
|
+
if (first_loop === NULL_POINTER) {
|
|
198
|
+
return 1;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let corner_count = 0;
|
|
202
|
+
let iter = first_loop;
|
|
203
|
+
|
|
204
|
+
do {
|
|
205
|
+
corner_count++;
|
|
206
|
+
iter = mesh.loop_read_next(iter);
|
|
207
|
+
} while (iter !== first_loop);
|
|
208
|
+
|
|
209
|
+
if (corner_count < 4) {
|
|
210
|
+
return 1;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
ensure_capacity(corner_count);
|
|
214
|
+
|
|
215
|
+
iter = first_loop;
|
|
216
|
+
|
|
217
|
+
for (let i = 0; i < corner_count; i++) {
|
|
218
|
+
_loops[i] = iter;
|
|
219
|
+
|
|
220
|
+
mesh.vertex_read_coordinate(_coordinate, 0, mesh.loop_read_vertex(iter));
|
|
221
|
+
|
|
222
|
+
_positions[i * 3] = _coordinate[0];
|
|
223
|
+
_positions[i * 3 + 1] = _coordinate[1];
|
|
224
|
+
_positions[i * 3 + 2] = _coordinate[2];
|
|
225
|
+
|
|
226
|
+
iter = mesh.loop_read_next(iter);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
polygon3_compute_normal(_normal, 0, _positions, 0, corner_count);
|
|
230
|
+
|
|
231
|
+
if (_normal[0] === 0 && _normal[1] === 0 && _normal[2] === 0) {
|
|
232
|
+
// no area, so no plane to project onto
|
|
233
|
+
return 1;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
_contour_ends[0] = corner_count;
|
|
237
|
+
|
|
238
|
+
const triangle_count = polygon3_triangulate(
|
|
239
|
+
_triangles, 0,
|
|
240
|
+
_positions, _contour_ends, 1,
|
|
241
|
+
_normal[0], _normal[1], _normal[2]
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
if (!is_ear_sequence(corner_count, triangle_count)) {
|
|
245
|
+
return 1;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
mesh.face_read_normal(_stored_normal, 0, face);
|
|
249
|
+
|
|
250
|
+
// The last triple is the residual triangle, which is what `face` itself
|
|
251
|
+
// becomes; the other n-3 are cut off it one at a time.
|
|
252
|
+
//
|
|
253
|
+
// The ring is re-walked alongside the cuts because each cut hands the shrunken
|
|
254
|
+
// polygon a NEW corner in place of the ear's predecessor -- `_loops` has to
|
|
255
|
+
// follow that swap or the next cut would reach into the triangle just made.
|
|
256
|
+
reset_ring(corner_count);
|
|
257
|
+
|
|
258
|
+
for (let t = 0; t < triangle_count - 1; t++) {
|
|
259
|
+
const ear = _triangles[t * 3 + 1];
|
|
260
|
+
const predecessor = _ring_prev[ear];
|
|
261
|
+
|
|
262
|
+
_loops[predecessor] = cut_ear(mesh, face, _loops[ear], _stored_normal);
|
|
263
|
+
|
|
264
|
+
unlink_ring(ear);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return triangle_count;
|
|
268
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run {@link bt_mesh_validate} and throw if the mesh is structurally broken.
|
|
3
|
+
*
|
|
4
|
+
* Uses a real `throw` rather than `assert.*` on purpose: `assert.*` is stripped
|
|
5
|
+
* from production bundles, and this is the check a spec relies on to fail. A
|
|
6
|
+
* caller that wants the free-in-production behaviour should call
|
|
7
|
+
* {@link bt_mesh_validate} inside its own `assert.ok(...)`.
|
|
8
|
+
*
|
|
9
|
+
* @param {BinaryTopology} mesh
|
|
10
|
+
* @param {string} [context] prepended to the message, e.g. the operation under test
|
|
11
|
+
* @throws {Error} when any structural invariant is broken
|
|
12
|
+
*
|
|
13
|
+
* @author Alex Goldring
|
|
14
|
+
* @copyright Company Named Limited (c) 2026
|
|
15
|
+
*/
|
|
16
|
+
export function bt_mesh_assert_valid(mesh: BinaryTopology, context?: string): void;
|
|
17
|
+
//# sourceMappingURL=bt_mesh_assert_valid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bt_mesh_assert_valid.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;GAcG;AACH,qEANW,MAAM,QAwBhB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { bt_mesh_validate } from "./bt_mesh_validate.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Maximum number of defects quoted in the thrown message. A corrupted cycle
|
|
5
|
+
* typically reports one defect per element on it, and a 10k-element dump helps
|
|
6
|
+
* nobody read the first one.
|
|
7
|
+
* @type {number}
|
|
8
|
+
*/
|
|
9
|
+
const REPORTED_DEFECT_LIMIT = 20;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Run {@link bt_mesh_validate} and throw if the mesh is structurally broken.
|
|
13
|
+
*
|
|
14
|
+
* Uses a real `throw` rather than `assert.*` on purpose: `assert.*` is stripped
|
|
15
|
+
* from production bundles, and this is the check a spec relies on to fail. A
|
|
16
|
+
* caller that wants the free-in-production behaviour should call
|
|
17
|
+
* {@link bt_mesh_validate} inside its own `assert.ok(...)`.
|
|
18
|
+
*
|
|
19
|
+
* @param {BinaryTopology} mesh
|
|
20
|
+
* @param {string} [context] prepended to the message, e.g. the operation under test
|
|
21
|
+
* @throws {Error} when any structural invariant is broken
|
|
22
|
+
*
|
|
23
|
+
* @author Alex Goldring
|
|
24
|
+
* @copyright Company Named Limited (c) 2026
|
|
25
|
+
*/
|
|
26
|
+
export function bt_mesh_assert_valid(mesh, context = "") {
|
|
27
|
+
const defects = bt_mesh_validate(mesh);
|
|
28
|
+
|
|
29
|
+
if (defects.length === 0) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const quoted = defects.slice(0, REPORTED_DEFECT_LIMIT);
|
|
34
|
+
|
|
35
|
+
const lines = quoted.map(d => ` [code ${d.code}] ${d.detail}`);
|
|
36
|
+
|
|
37
|
+
if (defects.length > quoted.length) {
|
|
38
|
+
lines.push(` ... and ${defects.length - quoted.length} more`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const prefix = context === "" ? "" : `${context}: `;
|
|
42
|
+
|
|
43
|
+
throw new Error(`${prefix}mesh has ${defects.length} structural defect(s)\n${lines.join("\n")}`);
|
|
44
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Number of loops on an edge's radial cycle, i.e. how many faces use that edge.
|
|
3
|
+
*
|
|
4
|
+
* `0` is a wire edge, `1` a boundary edge, `2` a manifold interior edge, and `3`
|
|
5
|
+
* or more a non-manifold edge. {@link bt_edge_is_boundary} answers the `1` case
|
|
6
|
+
* on its own; this is the counting version the manifoldness queries need.
|
|
7
|
+
*
|
|
8
|
+
* The walk is bounded by the loop pool's size so a corrupted radial cycle cannot
|
|
9
|
+
* hang the caller. A cycle that long is itself broken -- run
|
|
10
|
+
* {@link bt_mesh_validate} to find out where.
|
|
11
|
+
*
|
|
12
|
+
* @param {BinaryTopology} mesh
|
|
13
|
+
* @param {number} edge_id
|
|
14
|
+
* @returns {number}
|
|
15
|
+
*
|
|
16
|
+
* @author Alex Goldring
|
|
17
|
+
* @copyright Company Named Limited (c) 2026
|
|
18
|
+
*/
|
|
19
|
+
export function bt_mesh_count_edge_faces(mesh: BinaryTopology, edge_id: number): number;
|
|
20
|
+
//# sourceMappingURL=bt_mesh_count_edge_faces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bt_mesh_count_edge_faces.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,wEANW,MAAM,GACJ,MAAM,CAwBlB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { NULL_POINTER } from "../BinaryTopology.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Number of loops on an edge's radial cycle, i.e. how many faces use that edge.
|
|
5
|
+
*
|
|
6
|
+
* `0` is a wire edge, `1` a boundary edge, `2` a manifold interior edge, and `3`
|
|
7
|
+
* or more a non-manifold edge. {@link bt_edge_is_boundary} answers the `1` case
|
|
8
|
+
* on its own; this is the counting version the manifoldness queries need.
|
|
9
|
+
*
|
|
10
|
+
* The walk is bounded by the loop pool's size so a corrupted radial cycle cannot
|
|
11
|
+
* hang the caller. A cycle that long is itself broken -- run
|
|
12
|
+
* {@link bt_mesh_validate} to find out where.
|
|
13
|
+
*
|
|
14
|
+
* @param {BinaryTopology} mesh
|
|
15
|
+
* @param {number} edge_id
|
|
16
|
+
* @returns {number}
|
|
17
|
+
*
|
|
18
|
+
* @author Alex Goldring
|
|
19
|
+
* @copyright Company Named Limited (c) 2026
|
|
20
|
+
*/
|
|
21
|
+
export function bt_mesh_count_edge_faces(mesh, edge_id) {
|
|
22
|
+
const start = mesh.edge_read_loop(edge_id);
|
|
23
|
+
|
|
24
|
+
if (start === NULL_POINTER) {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const limit = mesh.loops.size;
|
|
29
|
+
|
|
30
|
+
let l = start;
|
|
31
|
+
let count = 0;
|
|
32
|
+
|
|
33
|
+
do {
|
|
34
|
+
count++;
|
|
35
|
+
|
|
36
|
+
l = mesh.loop_read_radial_next(l);
|
|
37
|
+
} while (l !== start && l !== NULL_POINTER && count <= limit);
|
|
38
|
+
|
|
39
|
+
return count;
|
|
40
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when every edge is used by exactly two faces -- a watertight surface with
|
|
3
|
+
* no boundary, no wire edges and no non-manifold edges.
|
|
4
|
+
*
|
|
5
|
+
* This is what "is this a solid?" means for volume, genus and inside/outside
|
|
6
|
+
* queries: {@link tri3_mesh_compute_signed_volume} is only meaningful on a closed
|
|
7
|
+
* mesh, and {@link bt_mesh_close_boundary_holes} exists to make an open one
|
|
8
|
+
* closed.
|
|
9
|
+
*
|
|
10
|
+
* An empty mesh is closed, vacuously -- there is no edge to violate the rule.
|
|
11
|
+
*
|
|
12
|
+
* @param {BinaryTopology} mesh
|
|
13
|
+
* @returns {boolean}
|
|
14
|
+
*
|
|
15
|
+
* @author Alex Goldring
|
|
16
|
+
* @copyright Company Named Limited (c) 2026
|
|
17
|
+
*/
|
|
18
|
+
export function bt_mesh_is_closed(mesh: BinaryTopology): boolean;
|
|
19
|
+
//# sourceMappingURL=bt_mesh_is_closed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bt_mesh_is_closed.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,yDALa,OAAO,CAmBnB"}
|