@woosh/meep-engine 2.164.0 → 2.165.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/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/core/binary/BitImage2.d.ts +91 -0
- package/src/core/binary/BitImage2.d.ts.map +1 -0
- package/src/core/binary/BitImage2.js +242 -0
- package/src/core/geom/2d/oriented-box/min_area_rect_2d.d.ts +22 -0
- package/src/core/geom/2d/oriented-box/min_area_rect_2d.d.ts.map +1 -0
- package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -0
- package/src/core/geom/2d/packing/skyline.d.ts +116 -0
- package/src/core/geom/2d/packing/skyline.d.ts.map +1 -0
- package/src/core/geom/2d/packing/skyline.js +258 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts +18 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts.map +1 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +86 -0
- package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -0
- package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -0
- package/src/core/geom/3d/atlas/Chart.d.ts +58 -0
- package/src/core/geom/3d/atlas/Chart.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/Chart.js +77 -0
- package/src/core/geom/3d/atlas/REVIEW_02.md +392 -0
- package/src/core/geom/3d/atlas/atlas_bench_lib.d.ts +73 -0
- package/src/core/geom/3d/atlas/atlas_bench_lib.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -0
- package/src/core/geom/3d/atlas/atlas_chart_type.d.ts +17 -0
- package/src/core/geom/3d/atlas/atlas_chart_type.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -0
- package/src/core/geom/3d/atlas/atlas_compute_charts.d.ts +25 -0
- package/src/core/geom/3d/atlas/atlas_compute_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -0
- package/src/core/geom/3d/atlas/atlas_extract_chart.d.ts +17 -0
- package/src/core/geom/3d/atlas/atlas_extract_chart.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -0
- package/src/core/geom/3d/atlas/atlas_generate.d.ts +39 -0
- package/src/core/geom/3d/atlas/atlas_generate.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_generate.js +43 -0
- package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts +84 -0
- package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -0
- package/src/core/geom/3d/atlas/atlas_write_chart_uvs.d.ts +25 -0
- package/src/core/geom/3d/atlas/atlas_write_chart_uvs.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.d.ts +22 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.d.ts +9 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -0
- package/src/core/geom/3d/atlas/data/atlas_build_face_areas.d.ts +9 -0
- package/src/core/geom/3d/atlas/data/atlas_build_face_areas.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -0
- package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.d.ts +27 -0
- package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -0
- package/src/core/geom/3d/atlas/io/bt_loop_uv.d.ts +22 -0
- package/src/core/geom/3d/atlas/io/bt_loop_uv.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/io/bt_loop_uv.js +57 -0
- package/src/core/geom/3d/atlas/pack/ChartPlacement.d.ts +36 -0
- package/src/core/geom/3d/atlas/pack/ChartPlacement.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -0
- package/src/core/geom/3d/atlas/pack/atlas_pack_charts.d.ts +62 -0
- package/src/core/geom/3d/atlas/pack/atlas_pack_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/pack/atlas_pack_charts.js +551 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_param_validity.d.ts +22 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_param_validity.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_param_validity.js +73 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.d.ts +37 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +270 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.d.ts +23 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +224 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.d.ts +14 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.d.ts +22 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -0
- package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.d.ts +20 -0
- package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -0
- package/src/core/geom/3d/atlas/param/fit_plane_basis.d.ts +27 -0
- package/src/core/geom/3d/atlas/param/fit_plane_basis.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -0
- package/src/core/geom/3d/atlas/segment/RegionGraph.d.ts +31 -0
- package/src/core/geom/3d/atlas/segment/RegionGraph.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -0
- package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.d.ts +23 -0
- package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -0
- package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.d.ts +24 -0
- package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts +27 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +113 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.d.ts +44 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +275 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.d.ts +22 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +199 -0
- package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.d.ts +32 -0
- package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.d.ts.map +1 -0
- package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.d.ts +20 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.d.ts.map +1 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +66 -0
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.d.ts.map +1 -1
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +13 -11
- package/src/core/geom/3d/sphere/sphere_compute_bounding_of_2_spheres.d.ts.map +1 -1
- package/src/core/geom/3d/sphere/sphere_compute_bounding_of_2_spheres.js +4 -3
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.js +4 -3
- package/src/core/geom/3d/topology/simplify/quadratic/Quadric3.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/quadratic/Quadric3.js +4 -3
- package/src/core/geom/3d/topology/simplify/quadratic/apply_border_penalty_to_vertex_quadrics.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/quadratic/apply_border_penalty_to_vertex_quadrics.js +10 -6
- package/src/core/geom/3d/topology/struct/TopoMesh.js +2 -2
- package/src/core/geom/3d/topology/struct/TopoTriangle.d.ts +0 -2
- package/src/core/geom/3d/topology/struct/TopoTriangle.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/TopoTriangle.js +2 -2
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +8 -27
- package/src/core/geom/vec3/v3_cotangent.d.ts +20 -0
- package/src/core/geom/vec3/v3_cotangent.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_cotangent.js +29 -0
- package/src/core/geom/vec3/v3_matrix3_multiply.d.ts +19 -0
- package/src/core/geom/vec3/v3_matrix3_multiply.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -0
- package/src/core/geom/vec3/v3_multiply.d.ts +16 -0
- package/src/core/geom/vec3/v3_multiply.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_multiply.js +19 -0
- package/src/core/math/linalg/cg/cg_solve.d.ts +24 -0
- package/src/core/math/linalg/cg/cg_solve.d.ts.map +1 -0
- package/src/core/math/linalg/cg/cg_solve.js +106 -0
- package/src/core/math/linalg/cg/cg_solve_normal_equations.d.ts +21 -0
- package/src/core/math/linalg/cg/cg_solve_normal_equations.d.ts.map +1 -0
- package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts +19 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -0
- package/src/core/math/linalg/sparse/SparseMatrixCSR.d.ts +50 -0
- package/src/core/math/linalg/sparse/SparseMatrixCSR.d.ts.map +1 -0
- package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -0
- package/src/core/math/linalg/sparse/spm_matvec.d.ts +9 -0
- package/src/core/math/linalg/sparse/spm_matvec.d.ts.map +1 -0
- package/src/core/math/linalg/sparse/spm_matvec.js +22 -0
- package/src/core/math/linalg/sparse/spm_matvec_transpose.d.ts +12 -0
- package/src/core/math/linalg/sparse/spm_matvec_transpose.d.ts.map +1 -0
- package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -0
- package/src/core/math/physics/mie/MIE_PARTICLES_STANDARD_PRECOMPUTED.d.ts +39 -0
- package/src/core/math/physics/mie/MIE_PARTICLES_STANDARD_PRECOMPUTED.js +22 -1
- package/src/core/math/physics/mie/compute_mie_particle_properties_rgb.d.ts.map +1 -1
- package/src/core/math/physics/mie/compute_mie_particle_properties_rgb.js +32 -9
- package/src/core/math/physics/mie/compute_mie_phase.d.ts +2 -3
- package/src/core/math/physics/mie/compute_mie_phase.d.ts.map +1 -1
- package/src/core/math/physics/mie/compute_mie_phase.js +1 -3
- package/src/core/math/physics/mie/lorenz_mie_coefs.d.ts +0 -1
- package/src/core/math/physics/mie/lorenz_mie_coefs.d.ts.map +1 -1
- package/src/core/math/physics/mie/lorenz_mie_coefs.js +0 -7
- package/src/engine/ecs/attachment/TransformAttachmentBinding.js +3 -3
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +2 -2
- package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/Terrain.js +4 -3
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +2 -2
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +9 -8
- package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics/GraphicsEngine.js +2 -1
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +2 -2
- package/src/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +0 -1
- package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.d.ts.map +1 -1
- package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +8 -7
- package/src/engine/graphics/geometry/MikkT/AvgTSpace.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/AvgTSpace.js +11 -6
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +2 -3
- package/src/engine/graphics/geometry/MikkT/CalcTexArea.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/CalcTexArea.js +3 -4
- package/src/engine/graphics/geometry/MikkT/DegenEpilogue.js +4 -4
- package/src/engine/graphics/geometry/MikkT/EvalTspace.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/EvalTspace.js +11 -8
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +7 -8
- package/src/engine/graphics/geometry/MikkT/GenerateTSpaces.js +8 -8
- package/src/engine/graphics/geometry/MikkT/InitTriInfo.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/InitTriInfo.js +30 -25
- package/src/engine/graphics/geometry/MikkT/MikkTSpace.js +7 -7
- package/src/engine/graphics/geometry/MikkT/NormalizeSafe.d.ts +0 -1
- package/src/engine/graphics/geometry/MikkT/NormalizeSafe.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/NormalizeSafe.js +6 -4
- package/src/engine/graphics/geometry/MikkT/STSpace.d.ts +0 -2
- package/src/engine/graphics/geometry/MikkT/STSpace.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/STSpace.js +3 -3
- package/src/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.d.ts +0 -2
- package/src/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.js +0 -1
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.d.ts +0 -2
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.js +4 -3
- package/src/engine/graphics/impostors/octahedral/grid/HemiOctahedralUvEncoder.js +2 -2
- package/src/engine/graphics/impostors/octahedral/grid/UvEncoder.d.ts +17 -7
- package/src/engine/graphics/impostors/voxel/VoxelImpostorBaker.js +2 -2
- package/src/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +3 -3
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +4 -3
- package/src/engine/graphics/render/forward_plus/LightManager.js +2 -2
- package/src/engine/graphics/render/forward_plus/model/Decal.d.ts +0 -2
- package/src/engine/graphics/render/forward_plus/model/Decal.d.ts.map +1 -1
- package/src/engine/graphics/render/forward_plus/model/Decal.js +3 -3
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +4 -3
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +6 -4
- package/src/engine/graphics/sh3/lightmap/ARTIFACTS_PLAN.md +146 -0
- package/src/engine/graphics/sh3/lightmap/CODE_REVIEW.md +121 -0
- package/src/engine/graphics/sh3/lightmap/LIGHTMAPPER_REVIEW.md +183 -0
- package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.d.ts +90 -0
- package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.js +678 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_build_geometry.d.ts +32 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_build_geometry.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_build_geometry.js +155 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_denoise.d.ts +49 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_denoise.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_denoise.js +136 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.d.ts +19 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.js +89 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_gather.d.ts +54 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_gather.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_gather.js +168 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_rasterize_triangle.d.ts +30 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_rasterize_triangle.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_rasterize_triangle.js +145 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_seam_fix.d.ts +38 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_seam_fix.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_seam_fix.js +152 -0
- package/src/engine/graphics/sh3/lightmap/prototypeLightmapBaker.d.ts +2 -0
- package/src/engine/graphics/sh3/lightmap/prototypeLightmapBaker.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/prototypeLightmapBaker.js +186 -0
- package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +2 -2
- package/src/engine/graphics/sh3/path_tracer/PathTracer.js +2 -2
- package/src/engine/graphics/sh3/path_tracer/prepare_scene_gltf.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/prepare_scene_gltf.js +6 -4
- package/src/engine/graphics/sh3/path_tracer/prototypePathTracer.js +3 -3
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +5 -4
- package/src/engine/graphics/sh3/sky/hosek/prototype_hosek.js +2 -2
- package/src/engine/input/devices/KeyboardDevice.d.ts +61 -14
- package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
- package/src/engine/input/devices/KeyboardDevice.js +41 -15
- package/src/engine/input/devices/isHTMLElementFocusable.d.ts.map +1 -1
- package/src/engine/input/devices/isHTMLElementFocusable.js +2 -9
- package/src/engine/sound/simulation/prototypeAcousticSolver.js +261 -143
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { tri3_area } from "../../triangle/tri3_area.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sander/Hoppe texture-stretch metric of a chart's UV map (xatlas
|
|
5
|
+
* `computeMetrics`). For each triangle it forms the parameterization gradients
|
|
6
|
+
* Ss = dq/du, St = dq/dv, whose first fundamental form `[[a,b],[b,c]]` has
|
|
7
|
+
* singular values Gamma_max, Gamma_min. The per-triangle L2 stretch is
|
|
8
|
+
* `(Gamma_max^2 + Gamma_min^2)/2 = (a + c)/2`.
|
|
9
|
+
*
|
|
10
|
+
* Results are normalized by the chart's global UV-to-3D linear scale, so a
|
|
11
|
+
* pure isometry OR any uniform similarity returns exactly 1; non-uniform
|
|
12
|
+
* distortion returns > 1. `mean_stretch` is the area-weighted RMS;
|
|
13
|
+
* `max_stretch` is the worst per-triangle Gamma_max.
|
|
14
|
+
*
|
|
15
|
+
* @param {Chart} chart
|
|
16
|
+
* @returns {{mean_stretch:number, max_stretch:number, geom_area:number, param_area:number}}
|
|
17
|
+
*/
|
|
18
|
+
export function atlas_chart_stretch_metric(chart) {
|
|
19
|
+
const uv = chart.uv;
|
|
20
|
+
const pos = chart.positions;
|
|
21
|
+
const tri = chart.tri_local;
|
|
22
|
+
const triangle_count = chart.triangle_count;
|
|
23
|
+
|
|
24
|
+
let total_geom = 0;
|
|
25
|
+
let total_param = 0;
|
|
26
|
+
let weighted_l2_sq = 0;
|
|
27
|
+
let max_gamma_sq = 0;
|
|
28
|
+
|
|
29
|
+
for (let t = 0; t < triangle_count; t++) {
|
|
30
|
+
const i0 = tri[t * 3];
|
|
31
|
+
const i1 = tri[t * 3 + 1];
|
|
32
|
+
const i2 = tri[t * 3 + 2];
|
|
33
|
+
|
|
34
|
+
const s1 = uv[i0 * 2], t1 = uv[i0 * 2 + 1];
|
|
35
|
+
const s2 = uv[i1 * 2], t2 = uv[i1 * 2 + 1];
|
|
36
|
+
const s3 = uv[i2 * 2], t3 = uv[i2 * 2 + 1];
|
|
37
|
+
|
|
38
|
+
const q1x = pos[i0 * 3], q1y = pos[i0 * 3 + 1], q1z = pos[i0 * 3 + 2];
|
|
39
|
+
const q2x = pos[i1 * 3], q2y = pos[i1 * 3 + 1], q2z = pos[i1 * 3 + 2];
|
|
40
|
+
const q3x = pos[i2 * 3], q3y = pos[i2 * 3 + 1], q3z = pos[i2 * 3 + 2];
|
|
41
|
+
|
|
42
|
+
const two_param_area = (s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1);
|
|
43
|
+
|
|
44
|
+
total_geom += tri3_area(q1x, q1y, q1z, q2x, q2y, q2z, q3x, q3y, q3z);
|
|
45
|
+
total_param += Math.abs(two_param_area) * 0.5;
|
|
46
|
+
|
|
47
|
+
if (Math.abs(two_param_area) < 1e-20) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const inv = 1 / two_param_area;
|
|
52
|
+
const ssx = (q1x * (t2 - t3) + q2x * (t3 - t1) + q3x * (t1 - t2)) * inv;
|
|
53
|
+
const ssy = (q1y * (t2 - t3) + q2y * (t3 - t1) + q3y * (t1 - t2)) * inv;
|
|
54
|
+
const ssz = (q1z * (t2 - t3) + q2z * (t3 - t1) + q3z * (t1 - t2)) * inv;
|
|
55
|
+
const stx = (q1x * (s3 - s2) + q2x * (s1 - s3) + q3x * (s2 - s1)) * inv;
|
|
56
|
+
const sty = (q1y * (s3 - s2) + q2y * (s1 - s3) + q3y * (s2 - s1)) * inv;
|
|
57
|
+
const stz = (q1z * (s3 - s2) + q2z * (s1 - s3) + q3z * (s2 - s1)) * inv;
|
|
58
|
+
|
|
59
|
+
const a = ssx * ssx + ssy * ssy + ssz * ssz;
|
|
60
|
+
const b = ssx * stx + ssy * sty + ssz * stz;
|
|
61
|
+
const c = stx * stx + sty * sty + stz * stz;
|
|
62
|
+
|
|
63
|
+
const geom_area = tri3_area(q1x, q1y, q1z, q2x, q2y, q2z, q3x, q3y, q3z);
|
|
64
|
+
weighted_l2_sq += ((a + c) / 2) * geom_area;
|
|
65
|
+
|
|
66
|
+
const disc = Math.sqrt(Math.max(0, (a - c) * (a - c) + 4 * b * b));
|
|
67
|
+
const gamma_max_sq = 0.5 * ((a + c) + disc);
|
|
68
|
+
if (gamma_max_sq > max_gamma_sq) {
|
|
69
|
+
max_gamma_sq = gamma_max_sq;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (total_geom <= 0 || total_param <= 0) {
|
|
74
|
+
return { mean_stretch: Infinity, max_stretch: Infinity, geom_area: total_geom, param_area: total_param };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Global linear scale^2 of the UV map relative to 3D (uv area / 3d area).
|
|
78
|
+
const scale_sq = total_param / total_geom;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
mean_stretch: Math.sqrt((weighted_l2_sq / total_geom) * scale_sq),
|
|
82
|
+
max_stretch: Math.sqrt(max_gamma_sq * scale_sq),
|
|
83
|
+
geom_area: total_geom,
|
|
84
|
+
param_area: total_param,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Region-grow piecewise re-segmentation (xatlas `PiecewiseParam`): split a chart
|
|
3
|
+
* whose LSCM map is still invalid into connected sub-charts that each
|
|
4
|
+
* parameterize bijectively by orthographic projection. Each sub-chart grows from
|
|
5
|
+
* a seed triangle, admitting an edge-adjacent triangle only if the projected
|
|
6
|
+
* sub-chart stays valid (no flip, no boundary self-intersection); a rejected
|
|
7
|
+
* triangle is left for a later sub-chart. A lone seed triangle is always valid,
|
|
8
|
+
* so this terminates and covers every triangle exactly once. Returned sub-charts
|
|
9
|
+
* are ortho-parameterized.
|
|
10
|
+
*
|
|
11
|
+
* (The validity re-check rebuilds the candidate each admission — O(k^2..k^3) for
|
|
12
|
+
* a k-triangle chart; acceptable for this rare fallback, an incremental check is
|
|
13
|
+
* a possible optimization.)
|
|
14
|
+
*
|
|
15
|
+
* @param {Chart} parent extracted chart (from atlas_extract_chart)
|
|
16
|
+
* @returns {Chart[]} ortho-parameterized sub-charts
|
|
17
|
+
*/
|
|
18
|
+
export function atlas_piecewise_resegment(parent: Chart): Chart[];
|
|
19
|
+
import { Chart } from "../Chart.js";
|
|
20
|
+
//# sourceMappingURL=atlas_piecewise_resegment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas_piecewise_resegment.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js"],"names":[],"mappings":"AA4GA;;;;;;;;;;;;;;;;GAgBG;AACH,kDAHW,KAAK,GACH,KAAK,EAAE,CAyCnB;sBApKqB,aAAa"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { Chart } from "../Chart.js";
|
|
2
|
+
import { atlas_chart_param_validity } from "./atlas_chart_param_validity.js";
|
|
3
|
+
import { atlas_chart_parameterize_ortho } from "./atlas_chart_parameterize_ortho.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build per-triangle adjacency within a chart: `tri_neighbor[t*3 + i]` is the
|
|
7
|
+
* triangle sharing edge i (between corner i and corner i+1) of triangle t, or
|
|
8
|
+
* -1 if that edge is a chart boundary. Internal edges of a manifold patch have
|
|
9
|
+
* exactly two triangles; a non-manifold edge keeps the first pairing.
|
|
10
|
+
*
|
|
11
|
+
* @param {Chart} chart
|
|
12
|
+
* @returns {Int32Array} per-triangle adjacency (3 entries per triangle, -1 = boundary)
|
|
13
|
+
*/
|
|
14
|
+
function build_triangle_adjacency(chart) {
|
|
15
|
+
const T = chart.triangle_count;
|
|
16
|
+
const VC = chart.vertex_count;
|
|
17
|
+
const tri_neighbor = new Int32Array(T * 3).fill(-1);
|
|
18
|
+
const edge_map = new Map();
|
|
19
|
+
|
|
20
|
+
for (let t = 0; t < T; t++) {
|
|
21
|
+
for (let i = 0; i < 3; i++) {
|
|
22
|
+
const a = chart.tri_local[t * 3 + i];
|
|
23
|
+
const b = chart.tri_local[t * 3 + ((i + 1) % 3)];
|
|
24
|
+
const key = a < b ? a * VC + b : b * VC + a;
|
|
25
|
+
|
|
26
|
+
const prev = edge_map.get(key);
|
|
27
|
+
if (prev === undefined) {
|
|
28
|
+
edge_map.set(key, t * 3 + i);
|
|
29
|
+
} else {
|
|
30
|
+
tri_neighbor[t * 3 + i] = (prev / 3) | 0;
|
|
31
|
+
tri_neighbor[prev] = t;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return tri_neighbor;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Build a standalone {@link Chart} from a subset of `parent`'s triangles.
|
|
40
|
+
*
|
|
41
|
+
* @param {Chart} parent chart whose triangles are being subset
|
|
42
|
+
* @param {number[]} tri_indices parent-triangle indices to include in the sub-chart
|
|
43
|
+
* @param {Int32Array} tri_neighbor per-triangle adjacency (3 entries per triangle, -1 = boundary)
|
|
44
|
+
* @returns {Chart} a standalone sub-chart
|
|
45
|
+
*/
|
|
46
|
+
function build_subchart(parent, tri_indices, tri_neighbor) {
|
|
47
|
+
const member = new Set(tri_indices);
|
|
48
|
+
const local_of_parent = new Map();
|
|
49
|
+
const vertex_of_local = [];
|
|
50
|
+
const positions = [];
|
|
51
|
+
const tri_local = [];
|
|
52
|
+
const tri_loops = [];
|
|
53
|
+
const tri_face = [];
|
|
54
|
+
const boundary_edges = [];
|
|
55
|
+
|
|
56
|
+
for (const t of tri_indices) {
|
|
57
|
+
const corners = [0, 0, 0];
|
|
58
|
+
for (let i = 0; i < 3; i++) {
|
|
59
|
+
const pv = parent.tri_local[t * 3 + i];
|
|
60
|
+
let sv = local_of_parent.get(pv);
|
|
61
|
+
if (sv === undefined) {
|
|
62
|
+
sv = vertex_of_local.length;
|
|
63
|
+
local_of_parent.set(pv, sv);
|
|
64
|
+
vertex_of_local.push(parent.vertex_of_local[pv]);
|
|
65
|
+
positions.push(parent.positions[pv * 3], parent.positions[pv * 3 + 1], parent.positions[pv * 3 + 2]);
|
|
66
|
+
}
|
|
67
|
+
corners[i] = sv;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
tri_local.push(corners[0], corners[1], corners[2]);
|
|
71
|
+
tri_loops.push(parent.tri_loops[t * 3], parent.tri_loops[t * 3 + 1], parent.tri_loops[t * 3 + 2]);
|
|
72
|
+
tri_face.push(parent.tri_face[t]);
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < 3; i++) {
|
|
75
|
+
const nb = tri_neighbor[t * 3 + i];
|
|
76
|
+
if (nb === -1 || !member.has(nb)) {
|
|
77
|
+
boundary_edges.push(corners[i], corners[(i + 1) % 3]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const sub = new Chart();
|
|
83
|
+
sub.vertex_count = vertex_of_local.length;
|
|
84
|
+
sub.vertex_of_local = Uint32Array.from(vertex_of_local);
|
|
85
|
+
sub.positions = Float64Array.from(positions);
|
|
86
|
+
sub.triangle_count = tri_face.length;
|
|
87
|
+
sub.tri_local = Uint32Array.from(tri_local);
|
|
88
|
+
sub.tri_loops = Uint32Array.from(tri_loops);
|
|
89
|
+
sub.tri_face = Uint32Array.from(tri_face);
|
|
90
|
+
sub.boundary_edges = Uint32Array.from(boundary_edges);
|
|
91
|
+
sub.uv = new Float64Array(vertex_of_local.length * 2);
|
|
92
|
+
return sub;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Ortho-parameterize `chart` and test whether the resulting UV layout is
|
|
97
|
+
* bijective: no mixed winding, no boundary self-intersection, and no zero-area
|
|
98
|
+
* triangles.
|
|
99
|
+
*
|
|
100
|
+
* @param {Chart} chart sub-chart from {@link build_subchart}
|
|
101
|
+
* @returns {boolean} true if the orthographic projection is a valid layout
|
|
102
|
+
*/
|
|
103
|
+
function is_ortho_valid(chart) {
|
|
104
|
+
atlas_chart_parameterize_ortho(chart);
|
|
105
|
+
const v = atlas_chart_param_validity(chart);
|
|
106
|
+
return !v.mixed_winding && !v.self_intersects && v.zero_area_count === 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Region-grow piecewise re-segmentation (xatlas `PiecewiseParam`): split a chart
|
|
111
|
+
* whose LSCM map is still invalid into connected sub-charts that each
|
|
112
|
+
* parameterize bijectively by orthographic projection. Each sub-chart grows from
|
|
113
|
+
* a seed triangle, admitting an edge-adjacent triangle only if the projected
|
|
114
|
+
* sub-chart stays valid (no flip, no boundary self-intersection); a rejected
|
|
115
|
+
* triangle is left for a later sub-chart. A lone seed triangle is always valid,
|
|
116
|
+
* so this terminates and covers every triangle exactly once. Returned sub-charts
|
|
117
|
+
* are ortho-parameterized.
|
|
118
|
+
*
|
|
119
|
+
* (The validity re-check rebuilds the candidate each admission — O(k^2..k^3) for
|
|
120
|
+
* a k-triangle chart; acceptable for this rare fallback, an incremental check is
|
|
121
|
+
* a possible optimization.)
|
|
122
|
+
*
|
|
123
|
+
* @param {Chart} parent extracted chart (from atlas_extract_chart)
|
|
124
|
+
* @returns {Chart[]} ortho-parameterized sub-charts
|
|
125
|
+
*/
|
|
126
|
+
export function atlas_piecewise_resegment(parent) {
|
|
127
|
+
const T = parent.triangle_count;
|
|
128
|
+
const tri_neighbor = build_triangle_adjacency(parent);
|
|
129
|
+
const assigned = new Uint8Array(T);
|
|
130
|
+
const subcharts = [];
|
|
131
|
+
|
|
132
|
+
for (let seed = 0; seed < T; seed++) {
|
|
133
|
+
if (assigned[seed]) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const subset = [seed];
|
|
138
|
+
assigned[seed] = 1;
|
|
139
|
+
|
|
140
|
+
const frontier = [];
|
|
141
|
+
push_neighbours(seed, tri_neighbor, assigned, frontier);
|
|
142
|
+
|
|
143
|
+
while (frontier.length > 0) {
|
|
144
|
+
const g = frontier.pop();
|
|
145
|
+
if (assigned[g]) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
subset.push(g);
|
|
150
|
+
const candidate = build_subchart(parent, subset, tri_neighbor);
|
|
151
|
+
if (is_ortho_valid(candidate)) {
|
|
152
|
+
assigned[g] = 1;
|
|
153
|
+
push_neighbours(g, tri_neighbor, assigned, frontier);
|
|
154
|
+
} else {
|
|
155
|
+
subset.pop();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const sub = build_subchart(parent, subset, tri_neighbor);
|
|
160
|
+
atlas_chart_parameterize_ortho(sub);
|
|
161
|
+
subcharts.push(sub);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return subcharts;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Push every not-yet-assigned edge-adjacent triangle of `t` onto the frontier.
|
|
169
|
+
*
|
|
170
|
+
* @param {number} t triangle index whose neighbours to enqueue
|
|
171
|
+
* @param {Int32Array} tri_neighbor per-triangle adjacency (3 entries per triangle, -1 = boundary)
|
|
172
|
+
* @param {Uint8Array} assigned 1 if a triangle is already claimed by a sub-chart
|
|
173
|
+
* @param {number[]} frontier growth queue of candidate triangle indices
|
|
174
|
+
* @returns {void}
|
|
175
|
+
*/
|
|
176
|
+
function push_neighbours(t, tri_neighbor, assigned, frontier) {
|
|
177
|
+
for (let i = 0; i < 3; i++) {
|
|
178
|
+
const nb = tri_neighbor[t * 3 + i];
|
|
179
|
+
if (nb !== -1 && !assigned[nb]) {
|
|
180
|
+
frontier.push(nb);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fit a proxy-plane orthonormal basis to a set of 3D points (xatlas
|
|
3
|
+
* `Fit::computeBasis`). The plane normal is the smallest-variance principal
|
|
4
|
+
* axis — the eigenvector of the smallest eigenvalue of the point covariance —
|
|
5
|
+
* and the tangent/bitangent span the plane.
|
|
6
|
+
*
|
|
7
|
+
* The basis is written tangent (ATLAS_BASIS_TANGENT), bitangent
|
|
8
|
+
* (ATLAS_BASIS_BITANGENT), normal (ATLAS_BASIS_NORMAL); project a point onto
|
|
9
|
+
* the chart with `u = dot(tangent, p)`, `v = dot(bitangent, p)`.
|
|
10
|
+
*
|
|
11
|
+
* Precondition: point_count >= 1; a meaningful plane needs >= 3 non-collinear
|
|
12
|
+
* points (a degenerate set still yields a valid orthonormal basis, just an
|
|
13
|
+
* arbitrary in-plane orientation).
|
|
14
|
+
*
|
|
15
|
+
* @param {Float32Array|Float64Array|number[]} out_basis length >= 9
|
|
16
|
+
* @param {Float32Array|Float64Array|number[]} points flat xyz, length >= 3*point_count
|
|
17
|
+
* @param {number} point_count
|
|
18
|
+
*/
|
|
19
|
+
export function fit_plane_basis(out_basis: Float32Array | Float64Array | number[], points: Float32Array | Float64Array | number[], point_count: number): void;
|
|
20
|
+
/**
|
|
21
|
+
* Offsets into a 9-float atlas basis. Layout matches
|
|
22
|
+
* {@link v3_orthonormal_matrix_from_normal}: tangent, bitangent, normal.
|
|
23
|
+
*/
|
|
24
|
+
export const ATLAS_BASIS_TANGENT: 0;
|
|
25
|
+
export const ATLAS_BASIS_BITANGENT: 3;
|
|
26
|
+
export const ATLAS_BASIS_NORMAL: 6;
|
|
27
|
+
//# sourceMappingURL=fit_plane_basis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fit_plane_basis.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/param/fit_plane_basis.js"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;GAiBG;AACH,2CAJW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,UAClC,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,eAClC,MAAM,QAkChB;AA9DD;;;GAGG;AACH,oCAAqC;AACrC,sCAAuC;AACvC,mCAAoC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { matrix_symmetric_3x3_eigen } from "../../../../math/linalg/eigen/matrix_symmetric_3x3_eigen.js";
|
|
2
|
+
import { v3_orthonormal_matrix_from_normal } from "../../../vec3/v3_orthonormal_matrix_from_normal.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Offsets into a 9-float atlas basis. Layout matches
|
|
6
|
+
* {@link v3_orthonormal_matrix_from_normal}: tangent, bitangent, normal.
|
|
7
|
+
*/
|
|
8
|
+
export const ATLAS_BASIS_TANGENT = 0;
|
|
9
|
+
export const ATLAS_BASIS_BITANGENT = 3;
|
|
10
|
+
export const ATLAS_BASIS_NORMAL = 6;
|
|
11
|
+
|
|
12
|
+
const _cov = new Float64Array(9);
|
|
13
|
+
const _values = new Float64Array(3);
|
|
14
|
+
const _vectors = new Float64Array(9);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Fit a proxy-plane orthonormal basis to a set of 3D points (xatlas
|
|
18
|
+
* `Fit::computeBasis`). The plane normal is the smallest-variance principal
|
|
19
|
+
* axis — the eigenvector of the smallest eigenvalue of the point covariance —
|
|
20
|
+
* and the tangent/bitangent span the plane.
|
|
21
|
+
*
|
|
22
|
+
* The basis is written tangent (ATLAS_BASIS_TANGENT), bitangent
|
|
23
|
+
* (ATLAS_BASIS_BITANGENT), normal (ATLAS_BASIS_NORMAL); project a point onto
|
|
24
|
+
* the chart with `u = dot(tangent, p)`, `v = dot(bitangent, p)`.
|
|
25
|
+
*
|
|
26
|
+
* Precondition: point_count >= 1; a meaningful plane needs >= 3 non-collinear
|
|
27
|
+
* points (a degenerate set still yields a valid orthonormal basis, just an
|
|
28
|
+
* arbitrary in-plane orientation).
|
|
29
|
+
*
|
|
30
|
+
* @param {Float32Array|Float64Array|number[]} out_basis length >= 9
|
|
31
|
+
* @param {Float32Array|Float64Array|number[]} points flat xyz, length >= 3*point_count
|
|
32
|
+
* @param {number} point_count
|
|
33
|
+
*/
|
|
34
|
+
export function fit_plane_basis(out_basis, points, point_count) {
|
|
35
|
+
let cx = 0, cy = 0, cz = 0;
|
|
36
|
+
for (let i = 0; i < point_count; i++) {
|
|
37
|
+
const i3 = i * 3;
|
|
38
|
+
cx += points[i3];
|
|
39
|
+
cy += points[i3 + 1];
|
|
40
|
+
cz += points[i3 + 2];
|
|
41
|
+
}
|
|
42
|
+
const inv = 1 / point_count;
|
|
43
|
+
cx *= inv;
|
|
44
|
+
cy *= inv;
|
|
45
|
+
cz *= inv;
|
|
46
|
+
|
|
47
|
+
let c00 = 0, c01 = 0, c02 = 0, c11 = 0, c12 = 0, c22 = 0;
|
|
48
|
+
for (let i = 0; i < point_count; i++) {
|
|
49
|
+
const i3 = i * 3;
|
|
50
|
+
const dx = points[i3] - cx;
|
|
51
|
+
const dy = points[i3 + 1] - cy;
|
|
52
|
+
const dz = points[i3 + 2] - cz;
|
|
53
|
+
c00 += dx * dx; c01 += dx * dy; c02 += dx * dz;
|
|
54
|
+
c11 += dy * dy; c12 += dy * dz;
|
|
55
|
+
c22 += dz * dz;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_cov[0] = c00; _cov[1] = c01; _cov[2] = c02;
|
|
59
|
+
_cov[3] = c01; _cov[4] = c11; _cov[5] = c12;
|
|
60
|
+
_cov[6] = c02; _cov[7] = c12; _cov[8] = c22;
|
|
61
|
+
|
|
62
|
+
matrix_symmetric_3x3_eigen(_values, _vectors, _cov);
|
|
63
|
+
|
|
64
|
+
// smallest eigenvalue is index 0 -> its eigenvector is the plane normal
|
|
65
|
+
v3_orthonormal_matrix_from_normal(out_basis, 0, _vectors[0], _vectors[1], _vectors[2]);
|
|
66
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Planar-region adjacency graph for region-atomic chart segmentation (the
|
|
3
|
+
* coarsening of a segmented mesh produced by {@link atlas_build_region_graph}).
|
|
4
|
+
* Each planar region is a node; adjacent region pairs are undirected CSR edges.
|
|
5
|
+
*
|
|
6
|
+
* Per-node arrays are indexed by region id; the CSR arrays (`adj`, `adj_shared`,
|
|
7
|
+
* `adj_seam`) are indexed by edge slot, with `offsets[r]..offsets[r+1]` giving
|
|
8
|
+
* region r's neighbour slots.
|
|
9
|
+
*
|
|
10
|
+
* @author Alex Goldring
|
|
11
|
+
* @copyright Company Named Limited (c) 2026
|
|
12
|
+
*/
|
|
13
|
+
export class RegionGraph {
|
|
14
|
+
/** Number of planar regions. @type {number} */
|
|
15
|
+
region_count: number;
|
|
16
|
+
/** Total 3D area per region. @type {Float32Array} */
|
|
17
|
+
region_area: Float32Array;
|
|
18
|
+
/** Area-weighted (un-normalized) normal accumulator per region — 3 floats each. @type {Float32Array} */
|
|
19
|
+
region_normal: Float32Array;
|
|
20
|
+
/** Boundary length per region. @type {Float32Array} */
|
|
21
|
+
region_boundary: Float32Array;
|
|
22
|
+
/** CSR row offsets, length region_count + 1. @type {Uint32Array} */
|
|
23
|
+
offsets: Uint32Array;
|
|
24
|
+
/** CSR neighbour region ids. @type {Uint32Array} */
|
|
25
|
+
adj: Uint32Array;
|
|
26
|
+
/** Shared boundary length per CSR edge slot. @type {Float32Array} */
|
|
27
|
+
adj_shared: Float32Array;
|
|
28
|
+
/** Accumulated normal-seam cost per CSR edge slot. @type {Float32Array} */
|
|
29
|
+
adj_seam: Float32Array;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=RegionGraph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionGraph.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/segment/RegionGraph.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH;IACI,+CAA+C;IAC/C,cADqC,MAAM,CAC1B;IAEjB,qDAAqD;IACrD,aADqC,YAAY,CACzB;IAExB,wGAAwG;IACxG,eADwF,YAAY,CAC1E;IAE1B,uDAAuD;IACvD,iBADuC,YAAY,CACvB;IAE5B,oEAAoE;IACpE,SADqD,WAAW,CAC5C;IAEpB,oDAAoD;IACpD,KADqC,WAAW,CAChC;IAEhB,qEAAqE;IACrE,YADqD,YAAY,CAC1C;IAEvB,2EAA2E;IAC3E,UAD2D,YAAY,CAClD;CACxB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const EMPTY_U32 = new Uint32Array(0);
|
|
2
|
+
const EMPTY_F32 = new Float32Array(0);
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Planar-region adjacency graph for region-atomic chart segmentation (the
|
|
6
|
+
* coarsening of a segmented mesh produced by {@link atlas_build_region_graph}).
|
|
7
|
+
* Each planar region is a node; adjacent region pairs are undirected CSR edges.
|
|
8
|
+
*
|
|
9
|
+
* Per-node arrays are indexed by region id; the CSR arrays (`adj`, `adj_shared`,
|
|
10
|
+
* `adj_seam`) are indexed by edge slot, with `offsets[r]..offsets[r+1]` giving
|
|
11
|
+
* region r's neighbour slots.
|
|
12
|
+
*
|
|
13
|
+
* @author Alex Goldring
|
|
14
|
+
* @copyright Company Named Limited (c) 2026
|
|
15
|
+
*/
|
|
16
|
+
export class RegionGraph {
|
|
17
|
+
/** Number of planar regions. @type {number} */
|
|
18
|
+
region_count = 0;
|
|
19
|
+
|
|
20
|
+
/** Total 3D area per region. @type {Float32Array} */
|
|
21
|
+
region_area = EMPTY_F32;
|
|
22
|
+
|
|
23
|
+
/** Area-weighted (un-normalized) normal accumulator per region — 3 floats each. @type {Float32Array} */
|
|
24
|
+
region_normal = EMPTY_F32;
|
|
25
|
+
|
|
26
|
+
/** Boundary length per region. @type {Float32Array} */
|
|
27
|
+
region_boundary = EMPTY_F32;
|
|
28
|
+
|
|
29
|
+
/** CSR row offsets, length region_count + 1. @type {Uint32Array} */
|
|
30
|
+
offsets = EMPTY_U32;
|
|
31
|
+
|
|
32
|
+
/** CSR neighbour region ids. @type {Uint32Array} */
|
|
33
|
+
adj = EMPTY_U32;
|
|
34
|
+
|
|
35
|
+
/** Shared boundary length per CSR edge slot. @type {Float32Array} */
|
|
36
|
+
adj_shared = EMPTY_F32;
|
|
37
|
+
|
|
38
|
+
/** Accumulated normal-seam cost per CSR edge slot. @type {Float32Array} */
|
|
39
|
+
adj_seam = EMPTY_F32;
|
|
40
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coarsen a segmented mesh into a planar-region adjacency graph for
|
|
3
|
+
* region-atomic chart growth (xatlas `nextRegionFace`). Each planar region
|
|
4
|
+
* (from {@link atlas_compute_planar_regions}) becomes a node carrying its total
|
|
5
|
+
* area, its area-weighted (un-normalized) normal accumulator, and its boundary
|
|
6
|
+
* length; each pair of adjacent regions becomes an undirected CSR edge carrying
|
|
7
|
+
* the shared boundary length and the accumulated normal-seam cost
|
|
8
|
+
* `Σ len·(1 − dihedral_dot)`.
|
|
9
|
+
*
|
|
10
|
+
* Precondition: face normals populated; `region_of_face` / `region_count` from
|
|
11
|
+
* atlas_compute_planar_regions; the AtlasData arrays from M1.
|
|
12
|
+
*
|
|
13
|
+
* @param {BinaryTopology} mesh
|
|
14
|
+
* @param {Uint32Array} region_of_face face -> region id (NULL_POINTER if unallocated)
|
|
15
|
+
* @param {number} region_count
|
|
16
|
+
* @param {Float32Array} face_areas
|
|
17
|
+
* @param {Float32Array} edge_lengths
|
|
18
|
+
* @param {Float32Array} edge_dihedrals
|
|
19
|
+
* @returns {RegionGraph}
|
|
20
|
+
*/
|
|
21
|
+
export function atlas_build_region_graph(mesh: BinaryTopology, region_of_face: Uint32Array, region_count: number, face_areas: Float32Array, edge_lengths: Float32Array, edge_dihedrals: Float32Array): RegionGraph;
|
|
22
|
+
import { RegionGraph } from "./RegionGraph.js";
|
|
23
|
+
//# sourceMappingURL=atlas_build_region_graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas_build_region_graph.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/segment/atlas_build_region_graph.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,+EAPW,WAAW,gBACX,MAAM,cACN,YAAY,gBACZ,YAAY,kBACZ,YAAY,GACV,WAAW,CAiHvB;4BArI2B,kBAAkB"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { NULL_POINTER } from "../../topology/struct/binary/BinaryTopology.js";
|
|
2
|
+
import { EDGE_DIHEDRAL_BOUNDARY } from "../data/atlas_build_edge_dihedrals.js";
|
|
3
|
+
import { RegionGraph } from "./RegionGraph.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Coarsen a segmented mesh into a planar-region adjacency graph for
|
|
7
|
+
* region-atomic chart growth (xatlas `nextRegionFace`). Each planar region
|
|
8
|
+
* (from {@link atlas_compute_planar_regions}) becomes a node carrying its total
|
|
9
|
+
* area, its area-weighted (un-normalized) normal accumulator, and its boundary
|
|
10
|
+
* length; each pair of adjacent regions becomes an undirected CSR edge carrying
|
|
11
|
+
* the shared boundary length and the accumulated normal-seam cost
|
|
12
|
+
* `Σ len·(1 − dihedral_dot)`.
|
|
13
|
+
*
|
|
14
|
+
* Precondition: face normals populated; `region_of_face` / `region_count` from
|
|
15
|
+
* atlas_compute_planar_regions; the AtlasData arrays from M1.
|
|
16
|
+
*
|
|
17
|
+
* @param {BinaryTopology} mesh
|
|
18
|
+
* @param {Uint32Array} region_of_face face -> region id (NULL_POINTER if unallocated)
|
|
19
|
+
* @param {number} region_count
|
|
20
|
+
* @param {Float32Array} face_areas
|
|
21
|
+
* @param {Float32Array} edge_lengths
|
|
22
|
+
* @param {Float32Array} edge_dihedrals
|
|
23
|
+
* @returns {RegionGraph}
|
|
24
|
+
*/
|
|
25
|
+
export function atlas_build_region_graph(mesh, region_of_face, region_count, face_areas, edge_lengths, edge_dihedrals) {
|
|
26
|
+
const faces = mesh.faces;
|
|
27
|
+
const face_count = faces.size;
|
|
28
|
+
|
|
29
|
+
const region_area = new Float32Array(region_count);
|
|
30
|
+
const region_normal = new Float32Array(region_count * 3);
|
|
31
|
+
const region_boundary = new Float32Array(region_count);
|
|
32
|
+
|
|
33
|
+
const fn = new Float32Array(3);
|
|
34
|
+
for (let f = 0; f < face_count; f++) {
|
|
35
|
+
if (!faces.is_allocated(f)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const r = region_of_face[f];
|
|
39
|
+
if (r === NULL_POINTER) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const a = face_areas[f];
|
|
43
|
+
region_area[r] += a;
|
|
44
|
+
mesh.face_read_normal(fn, 0, f);
|
|
45
|
+
region_normal[r * 3] += fn[0] * a;
|
|
46
|
+
region_normal[r * 3 + 1] += fn[1] * a;
|
|
47
|
+
region_normal[r * 3 + 2] += fn[2] * a;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const edges = mesh.edges;
|
|
51
|
+
const edge_count = edges.size;
|
|
52
|
+
const pair_map = new Map();
|
|
53
|
+
|
|
54
|
+
for (let e = 0; e < edge_count; e++) {
|
|
55
|
+
if (!edges.is_allocated(e)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const len = edge_lengths[e];
|
|
59
|
+
|
|
60
|
+
const l1 = mesh.edge_read_loop(e);
|
|
61
|
+
if (l1 === NULL_POINTER) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const l2 = mesh.loop_read_radial_next(l1);
|
|
65
|
+
|
|
66
|
+
if (l2 === l1) {
|
|
67
|
+
// mesh boundary edge -> boundary of its single region
|
|
68
|
+
const r = region_of_face[mesh.loop_read_face(l1)];
|
|
69
|
+
if (r !== NULL_POINTER) {
|
|
70
|
+
region_boundary[r] += len;
|
|
71
|
+
}
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const r1 = region_of_face[mesh.loop_read_face(l1)];
|
|
76
|
+
const r2 = region_of_face[mesh.loop_read_face(l2)];
|
|
77
|
+
if (r1 === r2 || r1 === NULL_POINTER || r2 === NULL_POINTER) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// region-boundary edge between r1 and r2
|
|
82
|
+
region_boundary[r1] += len;
|
|
83
|
+
region_boundary[r2] += len;
|
|
84
|
+
|
|
85
|
+
const a = r1 < r2 ? r1 : r2;
|
|
86
|
+
const b = r1 < r2 ? r2 : r1;
|
|
87
|
+
const key = a * region_count + b;
|
|
88
|
+
let rec = pair_map.get(key);
|
|
89
|
+
if (rec === undefined) {
|
|
90
|
+
rec = { a, b, len: 0, seam: 0 };
|
|
91
|
+
pair_map.set(key, rec);
|
|
92
|
+
}
|
|
93
|
+
const dih = edge_dihedrals[e];
|
|
94
|
+
const dd = dih === EDGE_DIHEDRAL_BOUNDARY ? 1 : dih;
|
|
95
|
+
rec.len += len;
|
|
96
|
+
rec.seam += len * (1 - dd);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Build the symmetric CSR adjacency from the pair map.
|
|
100
|
+
const degree = new Uint32Array(region_count);
|
|
101
|
+
for (const rec of pair_map.values()) {
|
|
102
|
+
degree[rec.a]++;
|
|
103
|
+
degree[rec.b]++;
|
|
104
|
+
}
|
|
105
|
+
const offsets = new Uint32Array(region_count + 1);
|
|
106
|
+
for (let r = 0; r < region_count; r++) {
|
|
107
|
+
offsets[r + 1] = offsets[r] + degree[r];
|
|
108
|
+
}
|
|
109
|
+
const adj_len = offsets[region_count];
|
|
110
|
+
const adj = new Uint32Array(adj_len);
|
|
111
|
+
const adj_shared = new Float32Array(adj_len);
|
|
112
|
+
const adj_seam = new Float32Array(adj_len);
|
|
113
|
+
|
|
114
|
+
const cursor = offsets.slice(0, region_count);
|
|
115
|
+
for (const rec of pair_map.values()) {
|
|
116
|
+
const ia = cursor[rec.a]++;
|
|
117
|
+
adj[ia] = rec.b;
|
|
118
|
+
adj_shared[ia] = rec.len;
|
|
119
|
+
adj_seam[ia] = rec.seam;
|
|
120
|
+
const ib = cursor[rec.b]++;
|
|
121
|
+
adj[ib] = rec.a;
|
|
122
|
+
adj_shared[ib] = rec.len;
|
|
123
|
+
adj_seam[ib] = rec.seam;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const graph = new RegionGraph();
|
|
127
|
+
graph.region_count = region_count;
|
|
128
|
+
graph.region_area = region_area;
|
|
129
|
+
graph.region_normal = region_normal;
|
|
130
|
+
graph.region_boundary = region_boundary;
|
|
131
|
+
graph.offsets = offsets;
|
|
132
|
+
graph.adj = adj;
|
|
133
|
+
graph.adj_shared = adj_shared;
|
|
134
|
+
graph.adj_seam = adj_seam;
|
|
135
|
+
return graph;
|
|
136
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge connected, (near-)coplanar faces into planar regions via union-find
|
|
3
|
+
* over interior edges (xatlas `computePlanarCharts` seeding). Two faces sharing
|
|
4
|
+
* an edge are unioned when the edge's adjacent-normal dot is >= 1 - tolerance.
|
|
5
|
+
* Boundary edges never merge across.
|
|
6
|
+
*
|
|
7
|
+
* @param {BinaryTopology} mesh
|
|
8
|
+
* @param {Float32Array} edge_dihedrals from {@link atlas_build_edge_dihedrals}
|
|
9
|
+
* @param {number} [coplanar_tolerance]
|
|
10
|
+
* @returns {{region_of_face: Uint32Array, region_count: number}} `region_of_face`
|
|
11
|
+
* maps each allocated face to a dense region id in [0, region_count);
|
|
12
|
+
* unallocated faces map to {@link NULL_POINTER}.
|
|
13
|
+
*/
|
|
14
|
+
export function atlas_compute_planar_regions(mesh: BinaryTopology, edge_dihedrals: Float32Array, coplanar_tolerance?: number): {
|
|
15
|
+
region_of_face: Uint32Array;
|
|
16
|
+
region_count: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* How close to coplanar (adjacent-normal dot == 1) two faces must be to merge
|
|
20
|
+
* into the same planar region. xatlas uses a strict kEpsilon coplanarity test.
|
|
21
|
+
* @type {number}
|
|
22
|
+
*/
|
|
23
|
+
export const ATLAS_COPLANAR_TOLERANCE: number;
|
|
24
|
+
//# sourceMappingURL=atlas_compute_planar_regions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas_compute_planar_regions.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;GAYG;AACH,mFANW,YAAY,uBACZ,MAAM;oBACa,WAAW;kBAAgB,MAAM;EAwD9D;AAxED;;;;GAIG;AACH,uCAFU,MAAM,CAE6B"}
|