@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,77 @@
|
|
|
1
|
+
import { uf_find, uf_init, uf_union } from "../../../../collection/union-find/union_find.js";
|
|
2
|
+
import { NULL_POINTER } from "../../topology/struct/binary/BinaryTopology.js";
|
|
3
|
+
import { EDGE_DIHEDRAL_BOUNDARY } from "../data/atlas_build_edge_dihedrals.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How close to coplanar (adjacent-normal dot == 1) two faces must be to merge
|
|
7
|
+
* into the same planar region. xatlas uses a strict kEpsilon coplanarity test.
|
|
8
|
+
* @type {number}
|
|
9
|
+
*/
|
|
10
|
+
export const ATLAS_COPLANAR_TOLERANCE = 1e-4;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Merge connected, (near-)coplanar faces into planar regions via union-find
|
|
14
|
+
* over interior edges (xatlas `computePlanarCharts` seeding). Two faces sharing
|
|
15
|
+
* an edge are unioned when the edge's adjacent-normal dot is >= 1 - tolerance.
|
|
16
|
+
* Boundary edges never merge across.
|
|
17
|
+
*
|
|
18
|
+
* @param {BinaryTopology} mesh
|
|
19
|
+
* @param {Float32Array} edge_dihedrals from {@link atlas_build_edge_dihedrals}
|
|
20
|
+
* @param {number} [coplanar_tolerance]
|
|
21
|
+
* @returns {{region_of_face: Uint32Array, region_count: number}} `region_of_face`
|
|
22
|
+
* maps each allocated face to a dense region id in [0, region_count);
|
|
23
|
+
* unallocated faces map to {@link NULL_POINTER}.
|
|
24
|
+
*/
|
|
25
|
+
export function atlas_compute_planar_regions(mesh, edge_dihedrals, coplanar_tolerance = ATLAS_COPLANAR_TOLERANCE) {
|
|
26
|
+
const faces = mesh.faces;
|
|
27
|
+
const face_count = faces.size;
|
|
28
|
+
|
|
29
|
+
const parent = new Uint32Array(face_count);
|
|
30
|
+
uf_init(parent, face_count);
|
|
31
|
+
|
|
32
|
+
const edges = mesh.edges;
|
|
33
|
+
const edge_count = edges.size;
|
|
34
|
+
const threshold = 1 - coplanar_tolerance;
|
|
35
|
+
|
|
36
|
+
for (let e = 0; e < edge_count; e++) {
|
|
37
|
+
if (!edges.is_allocated(e)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const d = edge_dihedrals[e];
|
|
42
|
+
if (d === EDGE_DIHEDRAL_BOUNDARY || d < threshold) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const l1 = mesh.edge_read_loop(e);
|
|
47
|
+
if (l1 === NULL_POINTER) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const l2 = mesh.loop_read_radial_next(l1);
|
|
51
|
+
if (l2 === l1) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
uf_union(parent, mesh.loop_read_face(l1), mesh.loop_read_face(l2));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const region_of_face = new Uint32Array(face_count);
|
|
59
|
+
const remap = new Uint32Array(face_count).fill(NULL_POINTER);
|
|
60
|
+
let region_count = 0;
|
|
61
|
+
|
|
62
|
+
for (let f = 0; f < face_count; f++) {
|
|
63
|
+
if (!faces.is_allocated(f)) {
|
|
64
|
+
region_of_face[f] = NULL_POINTER;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const root = uf_find(parent, f);
|
|
69
|
+
if (remap[root] === NULL_POINTER) {
|
|
70
|
+
remap[root] = region_count;
|
|
71
|
+
region_count++;
|
|
72
|
+
}
|
|
73
|
+
region_of_face[f] = remap[root];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return { region_of_face, region_count };
|
|
77
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Greedily merge adjacent charts whose area-weighted proxy normals are nearly
|
|
3
|
+
* aligned (xatlas `mergeCharts`, conservative variant), reducing over-
|
|
4
|
+
* segmentation left by the greedy seed+grow. Union-find over chart ids; proxy
|
|
5
|
+
* accumulators are summed as charts merge, so each test is against the current
|
|
6
|
+
* merged normal. Interior edges are visited in ascending id order, and the
|
|
7
|
+
* smaller chart id is always chosen as the union root, so the relabelling is
|
|
8
|
+
* deterministic. Coverage is preserved (every face keeps a chart; ids densified).
|
|
9
|
+
*
|
|
10
|
+
* This does NOT re-parameterize — the driver re-extracts and parameterizes the
|
|
11
|
+
* merged charts. Zero-area charts (degenerate proxy) are never merged.
|
|
12
|
+
*
|
|
13
|
+
* @param {BinaryTopology} mesh face normals populated
|
|
14
|
+
* @param {Int32Array} face_chart face -> chart id (-1 if none)
|
|
15
|
+
* @param {number} chart_count
|
|
16
|
+
* @param {Float32Array} face_areas
|
|
17
|
+
* @param {object} [options]
|
|
18
|
+
* @param {number} [options.mergeMinDot] min proxy-normal dot to merge (default 0.9)
|
|
19
|
+
* @returns {{face_chart: Int32Array, chart_count: number}}
|
|
20
|
+
*/
|
|
21
|
+
export function atlas_merge_charts(mesh: BinaryTopology, face_chart: Int32Array, chart_count: number, face_areas: Float32Array, options?: {
|
|
22
|
+
mergeMinDot?: number;
|
|
23
|
+
}): {
|
|
24
|
+
face_chart: Int32Array;
|
|
25
|
+
chart_count: number;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=atlas_merge_charts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas_merge_charts.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/segment/atlas_merge_charts.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qEAPW,UAAU,eACV,MAAM,cACN,YAAY;IAEK,WAAW,GAA5B,MAAM;IACJ;IAAC,UAAU,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAC,CAkFzD"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { NULL_POINTER } from "../../topology/struct/binary/BinaryTopology.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default minimum proxy-normal dot for a merge. Conservative (~25°): only
|
|
5
|
+
* near-coplanar adjacent charts merge, so the merged chart stays flat enough to
|
|
6
|
+
* parameterize without new distortion. xatlas uses 0.5 (~60°) but pairs it with
|
|
7
|
+
* a per-merge ortho re-validation we deliberately leave to the downstream
|
|
8
|
+
* parameterization (an over-aggressive merge that can't flatten simply falls back
|
|
9
|
+
* to LSCM/piecewise — and the metrics A/B gate catches any regression).
|
|
10
|
+
*/
|
|
11
|
+
const DEFAULT_MERGE_MIN_DOT = 0.9;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Greedily merge adjacent charts whose area-weighted proxy normals are nearly
|
|
15
|
+
* aligned (xatlas `mergeCharts`, conservative variant), reducing over-
|
|
16
|
+
* segmentation left by the greedy seed+grow. Union-find over chart ids; proxy
|
|
17
|
+
* accumulators are summed as charts merge, so each test is against the current
|
|
18
|
+
* merged normal. Interior edges are visited in ascending id order, and the
|
|
19
|
+
* smaller chart id is always chosen as the union root, so the relabelling is
|
|
20
|
+
* deterministic. Coverage is preserved (every face keeps a chart; ids densified).
|
|
21
|
+
*
|
|
22
|
+
* This does NOT re-parameterize — the driver re-extracts and parameterizes the
|
|
23
|
+
* merged charts. Zero-area charts (degenerate proxy) are never merged.
|
|
24
|
+
*
|
|
25
|
+
* @param {BinaryTopology} mesh face normals populated
|
|
26
|
+
* @param {Int32Array} face_chart face -> chart id (-1 if none)
|
|
27
|
+
* @param {number} chart_count
|
|
28
|
+
* @param {Float32Array} face_areas
|
|
29
|
+
* @param {object} [options]
|
|
30
|
+
* @param {number} [options.mergeMinDot] min proxy-normal dot to merge (default 0.9)
|
|
31
|
+
* @returns {{face_chart: Int32Array, chart_count: number}}
|
|
32
|
+
*/
|
|
33
|
+
export function atlas_merge_charts(mesh, face_chart, chart_count, face_areas, options = {}) {
|
|
34
|
+
const min_dot = options.mergeMinDot ?? DEFAULT_MERGE_MIN_DOT;
|
|
35
|
+
const faces = mesh.faces;
|
|
36
|
+
const face_count = faces.size;
|
|
37
|
+
|
|
38
|
+
// per-chart area-weighted (un-normalized) normal accumulator = the proxy
|
|
39
|
+
const proxy = new Float64Array(chart_count * 3);
|
|
40
|
+
const fn = new Float32Array(3);
|
|
41
|
+
for (let f = 0; f < face_count; f++) {
|
|
42
|
+
if (!faces.is_allocated(f)) continue;
|
|
43
|
+
const c = face_chart[f];
|
|
44
|
+
if (c < 0) continue;
|
|
45
|
+
const a = face_areas[f];
|
|
46
|
+
mesh.face_read_normal(fn, 0, f);
|
|
47
|
+
proxy[c * 3] += fn[0] * a;
|
|
48
|
+
proxy[c * 3 + 1] += fn[1] * a;
|
|
49
|
+
proxy[c * 3 + 2] += fn[2] * a;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const parent = new Int32Array(chart_count);
|
|
53
|
+
for (let c = 0; c < chart_count; c++) parent[c] = c;
|
|
54
|
+
|
|
55
|
+
/** @param {number} x @returns {number} root with path compression */
|
|
56
|
+
function find(x) {
|
|
57
|
+
while (parent[x] !== x) {
|
|
58
|
+
parent[x] = parent[parent[x]];
|
|
59
|
+
x = parent[x];
|
|
60
|
+
}
|
|
61
|
+
return x;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Whether two roots' proxy normals are within the merge cone. */
|
|
65
|
+
function aligned(a, b) {
|
|
66
|
+
const ax = proxy[a * 3], ay = proxy[a * 3 + 1], az = proxy[a * 3 + 2];
|
|
67
|
+
const bx = proxy[b * 3], by = proxy[b * 3 + 1], bz = proxy[b * 3 + 2];
|
|
68
|
+
const la = Math.sqrt(ax * ax + ay * ay + az * az);
|
|
69
|
+
const lb = Math.sqrt(bx * bx + by * by + bz * bz);
|
|
70
|
+
if (la === 0 || lb === 0) return false; // zero-area chart -> never merge
|
|
71
|
+
return (ax * bx + ay * by + az * bz) / (la * lb) >= min_dot;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const edges = mesh.edges;
|
|
75
|
+
const edge_count = edges.size;
|
|
76
|
+
for (let e = 0; e < edge_count; e++) {
|
|
77
|
+
if (!edges.is_allocated(e)) continue;
|
|
78
|
+
const l1 = mesh.edge_read_loop(e);
|
|
79
|
+
if (l1 === NULL_POINTER) continue;
|
|
80
|
+
const l2 = mesh.loop_read_radial_next(l1);
|
|
81
|
+
if (l2 === l1) continue; // mesh boundary edge
|
|
82
|
+
|
|
83
|
+
const c1 = face_chart[mesh.loop_read_face(l1)];
|
|
84
|
+
const c2 = face_chart[mesh.loop_read_face(l2)];
|
|
85
|
+
if (c1 < 0 || c2 < 0 || c1 === c2) continue;
|
|
86
|
+
|
|
87
|
+
const r1 = find(c1);
|
|
88
|
+
const r2 = find(c2);
|
|
89
|
+
if (r1 === r2 || !aligned(r1, r2)) continue;
|
|
90
|
+
|
|
91
|
+
const root = r1 < r2 ? r1 : r2;
|
|
92
|
+
const other = r1 < r2 ? r2 : r1;
|
|
93
|
+
parent[other] = root;
|
|
94
|
+
proxy[root * 3] += proxy[other * 3];
|
|
95
|
+
proxy[root * 3 + 1] += proxy[other * 3 + 1];
|
|
96
|
+
proxy[root * 3 + 2] += proxy[other * 3 + 2];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// densify root ids in ascending order
|
|
100
|
+
const dense = new Int32Array(chart_count).fill(-1);
|
|
101
|
+
let new_count = 0;
|
|
102
|
+
for (let c = 0; c < chart_count; c++) {
|
|
103
|
+
const r = find(c);
|
|
104
|
+
if (dense[r] === -1) dense[r] = new_count++;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const out = new Int32Array(face_count).fill(-1);
|
|
108
|
+
for (let f = 0; f < face_count; f++) {
|
|
109
|
+
const c = face_chart[f];
|
|
110
|
+
if (c >= 0) out[f] = dense[find(c)];
|
|
111
|
+
}
|
|
112
|
+
return { face_chart: out, chart_count: new_count };
|
|
113
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Greedy chart segmentation (xatlas `Atlas::computeCharts`, region-growing core).
|
|
3
|
+
* Charts are grown one at a time from the lowest-id unassigned face; each chart
|
|
4
|
+
* absorbs its cheapest edge-adjacent neighbour until the cheapest candidate's
|
|
5
|
+
* cost exceeds `maxCost`, then a new chart is seeded. Coverage is total — every
|
|
6
|
+
* allocated face ends in exactly one chart.
|
|
7
|
+
*
|
|
8
|
+
* The cost of adding a face is `normalDeviationWeight·N + normalSeamWeight·NS +
|
|
9
|
+
* roundnessWeight·R`, where N is the deviation of the face normal from the
|
|
10
|
+
* chart's running area-weighted normal, NS is the length-weighted normal
|
|
11
|
+
* discontinuity across the shared edges, and R is the relative isoperimetric
|
|
12
|
+
* (roundness) change. The candidate queue is a min-heap with lazy
|
|
13
|
+
* re-evaluation: a popped entry whose cost drifted is re-queued at its fresh
|
|
14
|
+
* cost before any face is committed, so commits always act on the true minimum.
|
|
15
|
+
*
|
|
16
|
+
* Determinism: seed order is ascending face id, the heap and cost are
|
|
17
|
+
* deterministic, and there is no wall-clock exit — the labelling is
|
|
18
|
+
* reproducible.
|
|
19
|
+
*
|
|
20
|
+
* Note: segmentation here is face-granular. xatlas grows whole coplanar regions
|
|
21
|
+
* atomically; that is a quality/perf refinement layered on the same cost and is
|
|
22
|
+
* a deferred follow-up.
|
|
23
|
+
*
|
|
24
|
+
* @param {BinaryTopology} mesh face normals must be populated
|
|
25
|
+
* @param {Float32Array} face_areas from atlas_build_face_areas
|
|
26
|
+
* @param {Float32Array} edge_lengths from atlas_build_edge_lengths
|
|
27
|
+
* @param {Float32Array} edge_dihedrals from atlas_build_edge_dihedrals
|
|
28
|
+
* @param {object} [options] overrides of {@link ATLAS_SEGMENT_DEFAULTS}
|
|
29
|
+
* @returns {{face_chart: Int32Array, chart_count: number}} `face_chart[f]` is the
|
|
30
|
+
* chart id of face f, or -1 for unallocated faces.
|
|
31
|
+
*/
|
|
32
|
+
export function atlas_segment_charts(mesh: BinaryTopology, face_areas: Float32Array, edge_lengths: Float32Array, edge_dihedrals: Float32Array, options?: object): {
|
|
33
|
+
face_chart: Int32Array;
|
|
34
|
+
chart_count: number;
|
|
35
|
+
};
|
|
36
|
+
export namespace ATLAS_SEGMENT_DEFAULTS {
|
|
37
|
+
let maxCost: number;
|
|
38
|
+
let normalDeviationWeight: number;
|
|
39
|
+
let normalSeamWeight: number;
|
|
40
|
+
let roundnessWeight: number;
|
|
41
|
+
let maxChartArea: number;
|
|
42
|
+
let maxBoundaryLength: number;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=atlas_segment_charts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas_segment_charts.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/segment/atlas_segment_charts.js"],"names":[],"mappings":"AAuCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,uEAPW,YAAY,gBACZ,YAAY,kBACZ,YAAY,YACZ,MAAM;gBACS,UAAU;iBAAe,MAAM;EA+MxD"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { IndexedFloatMinHeap } from "../../../../collection/heap/IndexedFloatMinHeap.js";
|
|
2
|
+
import { v3_dot } from "../../../vec3/v3_dot.js";
|
|
3
|
+
import { EDGE_DIHEDRAL_BOUNDARY } from "../data/atlas_build_edge_dihedrals.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Cost returned for a face that must not join the chart (hard reject). Never
|
|
7
|
+
* inserted into the heap.
|
|
8
|
+
* @type {number}
|
|
9
|
+
*/
|
|
10
|
+
const REJECT = Infinity;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Hard reject when the normal-deviation term reaches this — `1 - dot >= 0.707`
|
|
14
|
+
* is roughly a 73 degree fold away from the chart's running normal. Matches
|
|
15
|
+
* xatlas's `computeCost` hard cutoff.
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
18
|
+
const NORMAL_DEVIATION_REJECT = 0.707;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A heap entry is considered stale (recomputed against a drifted chart normal)
|
|
22
|
+
* when its fresh cost differs from the stored cost by more than this.
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
const STALE_EPSILON = 1e-6;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Default segmentation weights/limits (xatlas `ChartOptions`). The texture-seam
|
|
29
|
+
* term is intentionally absent: this port never ingests authored UVs.
|
|
30
|
+
*/
|
|
31
|
+
export const ATLAS_SEGMENT_DEFAULTS = {
|
|
32
|
+
maxCost: 2,
|
|
33
|
+
normalDeviationWeight: 2,
|
|
34
|
+
normalSeamWeight: 4,
|
|
35
|
+
roundnessWeight: 0.01,
|
|
36
|
+
maxChartArea: 0,
|
|
37
|
+
maxBoundaryLength: 0,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Greedy chart segmentation (xatlas `Atlas::computeCharts`, region-growing core).
|
|
42
|
+
* Charts are grown one at a time from the lowest-id unassigned face; each chart
|
|
43
|
+
* absorbs its cheapest edge-adjacent neighbour until the cheapest candidate's
|
|
44
|
+
* cost exceeds `maxCost`, then a new chart is seeded. Coverage is total — every
|
|
45
|
+
* allocated face ends in exactly one chart.
|
|
46
|
+
*
|
|
47
|
+
* The cost of adding a face is `normalDeviationWeight·N + normalSeamWeight·NS +
|
|
48
|
+
* roundnessWeight·R`, where N is the deviation of the face normal from the
|
|
49
|
+
* chart's running area-weighted normal, NS is the length-weighted normal
|
|
50
|
+
* discontinuity across the shared edges, and R is the relative isoperimetric
|
|
51
|
+
* (roundness) change. The candidate queue is a min-heap with lazy
|
|
52
|
+
* re-evaluation: a popped entry whose cost drifted is re-queued at its fresh
|
|
53
|
+
* cost before any face is committed, so commits always act on the true minimum.
|
|
54
|
+
*
|
|
55
|
+
* Determinism: seed order is ascending face id, the heap and cost are
|
|
56
|
+
* deterministic, and there is no wall-clock exit — the labelling is
|
|
57
|
+
* reproducible.
|
|
58
|
+
*
|
|
59
|
+
* Note: segmentation here is face-granular. xatlas grows whole coplanar regions
|
|
60
|
+
* atomically; that is a quality/perf refinement layered on the same cost and is
|
|
61
|
+
* a deferred follow-up.
|
|
62
|
+
*
|
|
63
|
+
* @param {BinaryTopology} mesh face normals must be populated
|
|
64
|
+
* @param {Float32Array} face_areas from atlas_build_face_areas
|
|
65
|
+
* @param {Float32Array} edge_lengths from atlas_build_edge_lengths
|
|
66
|
+
* @param {Float32Array} edge_dihedrals from atlas_build_edge_dihedrals
|
|
67
|
+
* @param {object} [options] overrides of {@link ATLAS_SEGMENT_DEFAULTS}
|
|
68
|
+
* @returns {{face_chart: Int32Array, chart_count: number}} `face_chart[f]` is the
|
|
69
|
+
* chart id of face f, or -1 for unallocated faces.
|
|
70
|
+
*/
|
|
71
|
+
export function atlas_segment_charts(mesh, face_areas, edge_lengths, edge_dihedrals, options = {}) {
|
|
72
|
+
const opt = { ...ATLAS_SEGMENT_DEFAULTS, ...options };
|
|
73
|
+
|
|
74
|
+
const faces = mesh.faces;
|
|
75
|
+
const face_count = faces.size;
|
|
76
|
+
|
|
77
|
+
const face_chart = new Int32Array(face_count).fill(-1);
|
|
78
|
+
const face_cost = new Float32Array(face_count);
|
|
79
|
+
const heap = new IndexedFloatMinHeap(face_count);
|
|
80
|
+
|
|
81
|
+
const fn = new Float32Array(3);
|
|
82
|
+
const cn = new Float32Array(3);
|
|
83
|
+
|
|
84
|
+
// Mutable state of the chart currently being grown.
|
|
85
|
+
let chart_id = 0;
|
|
86
|
+
let chart_area = 0;
|
|
87
|
+
let chart_boundary = 0;
|
|
88
|
+
let accum_x = 0, accum_y = 0, accum_z = 0;
|
|
89
|
+
|
|
90
|
+
// Output of the last evaluate() call, to avoid per-candidate allocation.
|
|
91
|
+
let out_area = 0;
|
|
92
|
+
let out_boundary = 0;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Normalize the chart's running area-weighted normal accumulator into `cn`.
|
|
96
|
+
*/
|
|
97
|
+
function chart_unit_normal() {
|
|
98
|
+
const len = Math.sqrt(accum_x * accum_x + accum_y * accum_y + accum_z * accum_z) || 1;
|
|
99
|
+
cn[0] = accum_x / len;
|
|
100
|
+
cn[1] = accum_y / len;
|
|
101
|
+
cn[2] = accum_z / len;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Sum of edge lengths around face f (its perimeter).
|
|
106
|
+
* @param {number} f face id
|
|
107
|
+
* @returns {number}
|
|
108
|
+
*/
|
|
109
|
+
function face_perimeter(f) {
|
|
110
|
+
let p = 0;
|
|
111
|
+
let l = mesh.face_read_loop(f);
|
|
112
|
+
const start = l;
|
|
113
|
+
do {
|
|
114
|
+
p += edge_lengths[mesh.loop_read_edge(l)];
|
|
115
|
+
l = mesh.loop_read_next(l);
|
|
116
|
+
} while (l !== start);
|
|
117
|
+
return p;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Cost of adding face g to the current chart, or REJECT. Side effect: sets
|
|
122
|
+
* out_area / out_boundary for the caller to commit.
|
|
123
|
+
* @param {number} g face id
|
|
124
|
+
* @returns {number}
|
|
125
|
+
*/
|
|
126
|
+
function evaluate(g) {
|
|
127
|
+
mesh.face_read_normal(fn, 0, g);
|
|
128
|
+
chart_unit_normal();
|
|
129
|
+
|
|
130
|
+
const dot = v3_dot(cn[0], cn[1], cn[2], fn[0], fn[1], fn[2]);
|
|
131
|
+
const N = Math.min(1 - dot, 1);
|
|
132
|
+
if (N >= NORMAL_DEVIATION_REJECT) {
|
|
133
|
+
return REJECT;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const new_area = chart_area + face_areas[g];
|
|
137
|
+
if (opt.maxChartArea > 0 && new_area > opt.maxChartArea) {
|
|
138
|
+
return REJECT;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let shared_len = 0;
|
|
142
|
+
let shared_seam = 0;
|
|
143
|
+
let boundary_delta = 0;
|
|
144
|
+
|
|
145
|
+
let l = mesh.face_read_loop(g);
|
|
146
|
+
const start = l;
|
|
147
|
+
do {
|
|
148
|
+
const e = mesh.loop_read_edge(l);
|
|
149
|
+
const len = edge_lengths[e];
|
|
150
|
+
const opp = mesh.loop_read_radial_next(l);
|
|
151
|
+
const opp_face = opp === l ? -1 : mesh.loop_read_face(opp);
|
|
152
|
+
|
|
153
|
+
if (opp_face !== -1 && face_chart[opp_face] === chart_id) {
|
|
154
|
+
shared_len += len;
|
|
155
|
+
const dih = edge_dihedrals[e];
|
|
156
|
+
const dd = dih === EDGE_DIHEDRAL_BOUNDARY ? 1 : dih;
|
|
157
|
+
shared_seam += len * (1 - dd);
|
|
158
|
+
boundary_delta -= len;
|
|
159
|
+
} else {
|
|
160
|
+
boundary_delta += len;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
l = mesh.loop_read_next(l);
|
|
164
|
+
} while (l !== start);
|
|
165
|
+
|
|
166
|
+
const new_boundary = chart_boundary + boundary_delta;
|
|
167
|
+
if (opt.maxBoundaryLength > 0 && new_boundary > opt.maxBoundaryLength) {
|
|
168
|
+
return REJECT;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const NS = shared_len > 0 ? shared_seam / shared_len : 0;
|
|
172
|
+
|
|
173
|
+
let R = 0;
|
|
174
|
+
if (chart_area > 0 && chart_boundary > 0 && new_boundary > 0) {
|
|
175
|
+
const old_ratio = (chart_boundary * chart_boundary) / chart_area;
|
|
176
|
+
const new_ratio = (new_boundary * new_boundary) / new_area;
|
|
177
|
+
R = 1 - old_ratio / new_ratio;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
out_area = new_area;
|
|
181
|
+
out_boundary = new_boundary;
|
|
182
|
+
|
|
183
|
+
return opt.normalDeviationWeight * N + opt.normalSeamWeight * NS + opt.roundnessWeight * R;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* (Re-)evaluate and (re-)queue every unallocated face edge-adjacent to f,
|
|
188
|
+
* caching each candidate's cost in `face_cost`.
|
|
189
|
+
* @param {number} f face id just committed to the current chart
|
|
190
|
+
*/
|
|
191
|
+
function push_neighbours(f) {
|
|
192
|
+
let l = mesh.face_read_loop(f);
|
|
193
|
+
const start = l;
|
|
194
|
+
do {
|
|
195
|
+
const opp = mesh.loop_read_radial_next(l);
|
|
196
|
+
if (opp !== l) {
|
|
197
|
+
const h = mesh.loop_read_face(opp);
|
|
198
|
+
if (faces.is_allocated(h) && face_chart[h] === -1) {
|
|
199
|
+
const c = evaluate(h);
|
|
200
|
+
if (c !== REJECT) {
|
|
201
|
+
if (heap.contains(h)) {
|
|
202
|
+
heap.update(h, c);
|
|
203
|
+
} else {
|
|
204
|
+
heap.insert(h, c);
|
|
205
|
+
}
|
|
206
|
+
face_cost[h] = c;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
l = mesh.loop_read_next(l);
|
|
211
|
+
} while (l !== start);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
let chart_count = 0;
|
|
215
|
+
|
|
216
|
+
for (let seed = 0; seed < face_count; seed++) {
|
|
217
|
+
if (!faces.is_allocated(seed) || face_chart[seed] !== -1) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
chart_id = chart_count;
|
|
222
|
+
chart_count++;
|
|
223
|
+
heap.clear();
|
|
224
|
+
|
|
225
|
+
face_chart[seed] = chart_id;
|
|
226
|
+
mesh.face_read_normal(fn, 0, seed);
|
|
227
|
+
const seed_area = face_areas[seed];
|
|
228
|
+
accum_x = fn[0] * seed_area;
|
|
229
|
+
accum_y = fn[1] * seed_area;
|
|
230
|
+
accum_z = fn[2] * seed_area;
|
|
231
|
+
chart_area = seed_area;
|
|
232
|
+
chart_boundary = face_perimeter(seed);
|
|
233
|
+
|
|
234
|
+
push_neighbours(seed);
|
|
235
|
+
|
|
236
|
+
for (;;) {
|
|
237
|
+
const g = heap.pop_min();
|
|
238
|
+
if (g === -1) {
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
if (face_chart[g] !== -1) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const stored = face_cost[g];
|
|
246
|
+
const fresh = evaluate(g);
|
|
247
|
+
|
|
248
|
+
if (fresh === REJECT) {
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (Math.abs(fresh - stored) > STALE_EPSILON) {
|
|
252
|
+
// Cost drifted with the chart normal — re-queue at the true value.
|
|
253
|
+
face_cost[g] = fresh;
|
|
254
|
+
heap.insert(g, fresh);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (fresh > opt.maxCost) {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
face_chart[g] = chart_id;
|
|
262
|
+
chart_area = out_area;
|
|
263
|
+
chart_boundary = out_boundary;
|
|
264
|
+
mesh.face_read_normal(fn, 0, g);
|
|
265
|
+
const ga = face_areas[g];
|
|
266
|
+
accum_x += fn[0] * ga;
|
|
267
|
+
accum_y += fn[1] * ga;
|
|
268
|
+
accum_z += fn[2] * ga;
|
|
269
|
+
|
|
270
|
+
push_neighbours(g);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return { face_chart, chart_count };
|
|
275
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Region-atomic chart segmentation (xatlas grows whole coplanar regions as
|
|
3
|
+
* units). Identical greedy structure and cost to {@link atlas_segment_charts},
|
|
4
|
+
* but the growth nodes are planar regions from {@link atlas_build_region_graph}
|
|
5
|
+
* rather than individual triangles: a chart absorbs an entire region at a time.
|
|
6
|
+
* This keeps coplanar faces together (no seam through a flat surface) and is
|
|
7
|
+
* far cheaper on flat-heavy meshes (the heap holds regions, not triangles).
|
|
8
|
+
*
|
|
9
|
+
* Cost = `normalDeviationWeight·N + normalSeamWeight·NS + roundnessWeight·R`,
|
|
10
|
+
* with the same 73-degree hard reject and optional area/boundary caps. The
|
|
11
|
+
* candidate queue uses the same lazy re-evaluation. Deterministic.
|
|
12
|
+
*
|
|
13
|
+
* @param {RegionGraph} region_graph from atlas_build_region_graph
|
|
14
|
+
* @param {Uint32Array} region_of_face face -> region id (NULL_POINTER if unallocated)
|
|
15
|
+
* @param {object} [options] overrides of ATLAS_SEGMENT_DEFAULTS
|
|
16
|
+
* @returns {{face_chart: Int32Array, chart_count: number}}
|
|
17
|
+
*/
|
|
18
|
+
export function atlas_segment_charts_atomic(region_graph: RegionGraph, region_of_face: Uint32Array, options?: object): {
|
|
19
|
+
face_chart: Int32Array;
|
|
20
|
+
chart_count: number;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=atlas_segment_charts_atomic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas_segment_charts_atomic.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;GAgBG;AACH,uFAJW,WAAW,YACX,MAAM;gBACS,UAAU;iBAAe,MAAM;EA6KxD"}
|