Skip to main content

High-performance OBJ merge and texture atlas pipeline

Project description

almeshmerge

High-performance OBJ merge and atlas generation library.

Build

chcp 65001 && uv build --wheel --out-dir dist

Local Build Matrix (Windows host + Docker Desktop)

Use this when you want to avoid GitHub Actions quota and build all wheels locally.

Target matrix:

  • Windows: cp311, cp312, cp313, cp314
  • Linux (manylinux via Docker): cp311, cp312, cp313, cp314

One-command build:

powershell -ExecutionPolicy Bypass -File .\scripts\build_local_wheels.ps1

The script will:

  • build Windows wheels with local Python 3.11~3.14
  • build Linux wheels with cibuildwheel in Docker
  • copy all wheels to a host folder like artifacts/wheelhouse/<timestamp>

Optional arguments:

# custom output folder on host
powershell -ExecutionPolicy Bypass -File .\scripts\build_local_wheels.ps1 -OutputDir "D:\wheel-output"

# build only Linux wheels
powershell -ExecutionPolicy Bypass -File .\scripts\build_local_wheels.ps1 -SkipWindows

# build only Windows wheels
powershell -ExecutionPolicy Bypass -File .\scripts\build_local_wheels.ps1 -SkipLinux

# build then upload from host (requires host-side PyPI credentials)
powershell -ExecutionPolicy Bypass -File .\scripts\build_local_wheels.ps1 -UploadToPyPI

If you prefer manual upload, run:

powershell -ExecutionPolicy Bypass -File .\scripts\upload_wheels.ps1 -WheelDir ".\artifacts\wheelhouse\<timestamp>"

CI Release (GitHub Actions)

  • Workflow: .github/workflows/release.yml
  • Trigger:
    • Push tag: v* (recommended, for example v0.1.29)
    • Manual run: workflow_dispatch
  • Build matrix:
    • OS: Linux (ubuntu-latest) and Windows (windows-latest)
    • Python: 3.11, 3.12, 3.13, 3.14 (wheel via cibuildwheel)
  • Publish:
    • Uses PyPI Trusted Publisher (OIDC), no API token required in repository secrets.
    • A pre-publish guard checks that tag version matches pyproject.toml version.

Recommended release commands:

git tag v0.1.29
git push github v0.1.29

If a run fails due to transient CI issues, rerun the failed jobs from the GitHub Actions UI or use workflow_dispatch.

Python API

from almeshmerge import merge_obj_to_atlas

result = merge_obj_to_atlas(
    input_objs=["a.obj", "b.obj"],
    output_dir="out",
    split_o=True,
    split_g=True,
    atlas_max_size=8192,
    atlas_padding=4,
    atlas_pow2=True,
    atlas_allow_rotate_90=True,
    atlas_max_count=0,
    spatial_cluster_radius=-1.0,
    atlas_target_utilization=0.92,
    uv_repeat_exclude_merge=True,
    simplify_ratio=0.8,
    vertex_key_mode="pos",  # default: keep topology vertex count stable
)
print(result)

Parameters

  • split_o: Whether to split by o objects.
  • split_g: Whether to split by g groups.
  • front_axis / up_axis: Input axis convention, defaults to Y-front and Z-up.
  • right_handed: Use right-handed axis transform.
  • atlas_max_size: Max atlas side length.
  • atlas_padding: Padding pixels between packed textures.
    • Default is 4.
    • For Blender viewport preview, 8 or higher is often safer if you see tile-edge bleed.
    • In Blender, prefer Image Texture Extension=Extend or Clip for atlas materials.
  • atlas_pow2: Force atlas width/height to powers of two.
  • atlas_allow_rotate_90: Allow 90-degree placement rotation.
  • atlas_max_count: Max number of generated atlases (0 means unlimited).
  • spatial_cluster_radius: Spatial clustering radius for unit-wise texture packing (<=0 disables clustering).
  • atlas_target_utilization: Target utilization threshold used to trigger extra packing refinement.
  • uv_repeat_exclude_merge: Exclude UV-repeat units from merge and keep them as original textures.
  • simplify_ratio: Mesh simplification ratio before export.
  • vertex_key_mode: Export dedup key mode. pos is default and keeps topology vertex count stable while writing split v/vt/vn indices; pos_uv ignores normal in dedup; full keeps position+UV+normal in a unified index.

Diagnostics for Atlas Stability

merge_obj_to_atlas() now returns extra diagnostics that help locate parameter-sensitive texture issues:

  • diagnostics.atlas_rot90_count / diagnostics.atlas_rot90_ratio
  • diagnostics.uv_edge_01_hits / diagnostics.uv_near_edge_hits
  • compose_diagnostics.crop_size_mismatch_count
  • compose_diagnostics.crop_size_mismatches (first 20 samples)

Interpretation:

  • crop_size_mismatch_count == 0 means C++ crop estimation and Python crop execution are consistent.
  • uv_edge_01_hits == 0 means remapped UVs do not collapse to exact 0/1 boundaries.
  • Large changes in atlas_rot90_ratio across parameter sets are expected and indicate different packing paths.

Regression Matrix (Recommended)

For Blender preview stability, run at least:

  • atlas_padding: 4, 8
  • atlas_max_size: 2048, 4096, 8192

Pass criteria:

  • No visible large-scale texture scramble in Blender.
  • compose_diagnostics.crop_size_mismatch_count == 0.
  • diagnostics.uv_edge_01_hits == 0.

 

本地构建

# 构建全部 8 个 wheel
.\scripts\build_local_wheels.ps1

# 只构建 Windows
.\scripts\build_local_wheels.ps1 -SkipLinux

# 只构建 Linux
.\scripts\build_local_wheels.ps1 -SkipWindows

# 上传(自动找最新构建目录)
.\scripts\upload_wheels.ps1

# 构建完直接上传
.\scripts\build_local_wheels.ps1 -UploadToPyPI

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

almeshmerge-0.1.39-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (441.2 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

almeshmerge-0.1.39-cp313-cp313-win_amd64.whl (142.8 kB view details)

Uploaded CPython 3.13Windows x86-64

almeshmerge-0.1.39-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (441.1 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

almeshmerge-0.1.39-cp312-cp312-win_amd64.whl (143.4 kB view details)

Uploaded CPython 3.12Windows x86-64

almeshmerge-0.1.39-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (441.5 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

almeshmerge-0.1.39-cp311-cp311-win_amd64.whl (143.0 kB view details)

Uploaded CPython 3.11Windows x86-64

almeshmerge-0.1.39-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (441.5 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file almeshmerge-0.1.39-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.39-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 6cb18b0738cc34117395dfe5d35d0aede9c1a9aeae00f48baeed095bf7624220
MD5 0134b488855b09e03f5d00a2406abc41
BLAKE2b-256 505e3519a77b7bccfacc18a900afc360b0ecb091ca5b5f67c435ebb58873cf23

See more details on using hashes here.

File details

Details for the file almeshmerge-0.1.39-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.39-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 46356c1356891104765bc761c1e74bfae266ad137df978959900261a637aeac4
MD5 3d21ce5333ea5f7cb4369b79a838bd8e
BLAKE2b-256 c2829dd7746074e76d652e507d23dba562bfa304cdc9287915b96546e49ebbc5

See more details on using hashes here.

File details

Details for the file almeshmerge-0.1.39-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.39-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1df2ec450443c4c29534d0f256b8aa4d66b969d618d515212fdf7dacbd5fae40
MD5 cb113cae7ec0f42bdf9f6575e40594e9
BLAKE2b-256 2eb46eb7a915ea9522c0e7956b6e8975cebce7e345f8691dad6c5e04feef457e

See more details on using hashes here.

File details

Details for the file almeshmerge-0.1.39-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.39-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b29f18e355eaf30513a63375eb31df14d61af7944129cfa076b02e95b6cf501c
MD5 3af74af6ab4e5f1dfbdf42ccf37eb2a7
BLAKE2b-256 c2fea75184da4408a943e18bdc218471994d56f7bf02147252e436a89d17db99

See more details on using hashes here.

File details

Details for the file almeshmerge-0.1.39-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.39-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a83004357e0520ade80ad9e2a00cc67f4e3d1414e891724fe1057d259e5a13f0
MD5 e29177be80282c8a825d945914309138
BLAKE2b-256 2ecc653a3febef270bfc0f54efb156ab5efa99beed5b66a25090517dce374da7

See more details on using hashes here.

File details

Details for the file almeshmerge-0.1.39-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.39-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 4c83648b34b14916a7ec7db8e0fcc90c35381860d7f61bfaa9dcc91e698751e5
MD5 f89b385efc0d647fb6a67fa5fcaa1fae
BLAKE2b-256 c407ab1d4ecf59ff5aa200ab5ce6671e89d82193b995082840139ec269c93aa1

See more details on using hashes here.

File details

Details for the file almeshmerge-0.1.39-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.39-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a96ac668403c0066dc207b695cf70a48ae4651e7aaba9a5fcdfa2bea3c8a4f77
MD5 9972397c7dc105748b81b98cc2474951
BLAKE2b-256 8defb03b2bd5f8c3eb0bc2f0b07dc4732c20b5d1608c17fa5f0c63aa80f524cb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page