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.41-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.41-cp313-cp313-win_amd64.whl (142.1 kB view details)

Uploaded CPython 3.13Windows x86-64

almeshmerge-0.1.41-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (440.2 kB view details)

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

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

Uploaded CPython 3.12Windows x86-64

almeshmerge-0.1.41-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (440.8 kB view details)

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

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

Uploaded CPython 3.11Windows x86-64

almeshmerge-0.1.41-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.41-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for almeshmerge-0.1.41-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a379e8b85d25f65cd5be49e794b5bf080ebe9b33ebf32f2210c99a5ea999813e
MD5 f634a850d3dda8c1923bd3529d643d8c
BLAKE2b-256 04bcfb96e62bac02824117f4b73896003e7d2cac903173f5801c0f1cfcf384a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.41-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 58b11ee72e48e07552d346a76f0603cbac3fbb08caa5f31563860f87c0fbf0ad
MD5 bdfc208f271c893b266a6e506d05b1f7
BLAKE2b-256 3edb7d1eb9b2de36de40bad3cc0584bc59d865e40343d7063c7537daa723e030

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.41-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b3edee9994ffce142e8b9a0a56b2459f0d2efb726833e87733a68b458777440b
MD5 628a8025ab7d6a0d1ce0f24a7699aa6f
BLAKE2b-256 3b215d62c6ff55abd9f7a6e8379d713aa6113d193282fb80128789d6c9b15e4c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.41-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b2cfacd2508741000d2eda4e79e4dbd8dcc0ca55da92b1055033b845c5a920f4
MD5 de3ca1671ac89e6a12e41f82f83aac5c
BLAKE2b-256 07d6057dc5c313be7f46c0b9f75419a20232f2b340a9edce10c3e24abe9008af

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.41-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 476da5bd96426c57dfd747c35a97c2b38b2eeec1b6448b881bafcda3db16f24e
MD5 463ee0ffe9a8e52f52c6feabe69528be
BLAKE2b-256 4540423618aca4ccd7f205253b0844514584d38c3f0b1c3daf4b17dea9883b5a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.41-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 243d4930a851765a9cbe49ea1150a88d7ff819ad2a373c44b2dbb163f824b474
MD5 3107b08561e6dc2479ff740ba8a34448
BLAKE2b-256 d8d3253edbcdf08761d38f94d269cfcd9d7931402acfd922784ed95a55156374

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for almeshmerge-0.1.41-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 53fe92104bc093f9a6ff3afb513e6247f5f7d934c3d65bf274e51cfe63482ca1
MD5 304ccb7f21360c05d08a0fe7e2b4f905
BLAKE2b-256 6b2568499dcbb1312c418fc583a908627c82a02ebad61f8ce6a69c631d60bf19

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