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.40-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (440.5 kB view details)

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

almeshmerge-0.1.40-cp313-cp313-win_amd64.whl (142.0 kB view details)

Uploaded CPython 3.13Windows x86-64

almeshmerge-0.1.40-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (440.3 kB view details)

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

almeshmerge-0.1.40-cp312-cp312-win_amd64.whl (142.7 kB view details)

Uploaded CPython 3.12Windows x86-64

almeshmerge-0.1.40-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (440.9 kB view details)

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

almeshmerge-0.1.40-cp311-cp311-win_amd64.whl (142.3 kB view details)

Uploaded CPython 3.11Windows x86-64

almeshmerge-0.1.40-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (440.3 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.40-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.40-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 03e56bbc92385a92efe693572e93c640b42d172cb370d16e8aac3568509d0fa7
MD5 54f56b8df0ab6e2a3f8b5466b2df9442
BLAKE2b-256 e8ef64bd1689e40da96da23bb0597b07cc0f3620adf73992d33923847882206c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.40-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 68b871cd6e79122ed0295176d59026bfc7135207dbd9af6f268e8a7d1f28b8f0
MD5 ed33ed732f4a6f9856677d5655e4f050
BLAKE2b-256 aa384790675ced9e5a009ee31d1f7e9ecc819d896eae499bcea3dcb1879cb0b9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.40-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0ace49f2c03dac5bce122264eef486c7aa15fa8268370fde4fc26995e7059a53
MD5 bddaa3daa3cbf5bd28d1fc8bca71b0b9
BLAKE2b-256 bebe6feb5bc683f555737f3003b81547997dd94cea532331f6da5af3c5c74ff0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.40-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 d91784242dbf80489cc639e87e7400f3e36cd4e54c2957e8257f0eb1f2fe0ef9
MD5 764d350b8858c66f9b2ecb42bc0db1b7
BLAKE2b-256 1a1638e70c1287be7bc6dcb6b72eaad9c399529c4d65d295fd5a3c3609878632

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.40-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 582cab5e80c4b6283724b5d2f241fae55a12f5466725586fd23ed53dbb6c08f6
MD5 21addd461032966d7d3e75dbbf63f162
BLAKE2b-256 c02ff33e13b62da7a4929396bb13077fadd0165f5eae633f7989baa76ef5a30b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.40-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 96e4e408663f35103972c1218f9044a83f051485a65de9a138bad0e6ef047c11
MD5 68ff9f8accb8705fa96b523dfeedd194
BLAKE2b-256 688a8f9112e5056f9422a16bcd8c954f20d1ad1032803105d2dd24aa83bc8f71

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.40-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ea44daf96bbdb752eb448fd18ac8cb63fdafa0cba3803fef9caf4d7a3f52f967
MD5 5e9dd76ca0651863b7c95f713263edd0
BLAKE2b-256 3e6df6ccf5ad76ee59cbeca495a5fa0d6436a52e3d7001348e3e8dddf17a378b

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