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
cibuildwheelin 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 examplev0.1.29) - Manual run:
workflow_dispatch
- Push tag:
- Build matrix:
- OS: Linux (
ubuntu-latest) and Windows (windows-latest) - Python:
3.11,3.12,3.13,3.14(wheel viacibuildwheel)
- OS: Linux (
- Publish:
- Uses PyPI Trusted Publisher (OIDC), no API token required in repository secrets.
- A pre-publish guard checks that tag version matches
pyproject.tomlversion.
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 byoobjects.split_g: Whether to split byggroups.front_axis/up_axis: Input axis convention, defaults toY-front andZ-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,
8or higher is often safer if you see tile-edge bleed. - In Blender, prefer Image Texture
Extension=ExtendorClipfor atlas materials.
- Default is
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 (0means unlimited).spatial_cluster_radius: Spatial clustering radius for unit-wise texture packing (<=0disables 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.posis default and keeps topology vertex count stable while writing splitv/vt/vnindices;pos_uvignores normal in dedup;fullkeeps 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_ratiodiagnostics.uv_edge_01_hits/diagnostics.uv_near_edge_hitscompose_diagnostics.crop_size_mismatch_countcompose_diagnostics.crop_size_mismatches(first 20 samples)
Interpretation:
crop_size_mismatch_count == 0means C++ crop estimation and Python crop execution are consistent.uv_edge_01_hits == 0means remapped UVs do not collapse to exact 0/1 boundaries.- Large changes in
atlas_rot90_ratioacross parameter sets are expected and indicate different packing paths.
Regression Matrix (Recommended)
For Blender preview stability, run at least:
atlas_padding:4,8atlas_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
本地构建 Debug 版本
# 仅构建
.\scripts\build_debug_wheel.ps1
# 构建并上传
.\scripts\build_debug_wheel.ps1 -UploadToPyPI
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file almeshmerge-0.1.48-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: almeshmerge-0.1.48-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 440.1 kB
- Tags: CPython 3.14, manylinux: glibc 2.24+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f117b3012ca96919a7a0e85db89b925044bb56ff9ef15c197951f9db6e189beb
|
|
| MD5 |
3d45c7e8ab6a5d31738ae6d99d8e0fe4
|
|
| BLAKE2b-256 |
272bbc57ad398c4725494250c9e7fea9fcf816a870c6db0b1e8b0476f6ecba1a
|
File details
Details for the file almeshmerge-0.1.48-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: almeshmerge-0.1.48-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 141.7 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
514c80af3533be450d5f154f0cc8cc0506c5d83da6766fb8e0d2fa638089f202
|
|
| MD5 |
5b790f09d0246e03129d6803e22b4f72
|
|
| BLAKE2b-256 |
abe11ae88c8d230fbf331a4d693aa01f17eeee55e2d3fdab5c6b7ec6db9afcec
|
File details
Details for the file almeshmerge-0.1.48-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: almeshmerge-0.1.48-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 440.1 kB
- Tags: CPython 3.13, manylinux: glibc 2.24+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
099c587f944fd45446fb3ee780ebe40bebe0ddbd6a40a3b6afbe5d746a2e82d0
|
|
| MD5 |
6f6a20af748de3ecef244ef7d0f347d6
|
|
| BLAKE2b-256 |
b6ceb14b940c8886f02646eded5f3c31813dcfcbef50f3f863286031caf62fb5
|
File details
Details for the file almeshmerge-0.1.48-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: almeshmerge-0.1.48-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 142.5 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9c0a1b795b63a63ae1daa057e470b403845d46a746f3814b2519af1beff43a2
|
|
| MD5 |
729d94b3bf383aaabf9311fef8491108
|
|
| BLAKE2b-256 |
629e1025311039c3604b0471b3cfd78e3fbf4f98750433adb3cfe1639353d2c6
|
File details
Details for the file almeshmerge-0.1.48-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: almeshmerge-0.1.48-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 440.6 kB
- Tags: CPython 3.12, manylinux: glibc 2.24+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4429a4aeac3047410c56bba56d0947b1ba1efbe91ae4228592a4028d4fe24c26
|
|
| MD5 |
32d70e057f8aff844fee7d801adf17e0
|
|
| BLAKE2b-256 |
5acad82462b315de969c9f86d2a6b333f7ca844c6d60ab7743d95051635f50f4
|
File details
Details for the file almeshmerge-0.1.48-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: almeshmerge-0.1.48-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 142.0 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68a316b8b729503f39d8568a14789ae08ec9d0713cf3479dc0c01377d6c4b89b
|
|
| MD5 |
19da6c8e3bd057425f78c18bc869e27a
|
|
| BLAKE2b-256 |
ad3f2f1f4253e9726b95d4dedeb4e89fbad27a8edb156e038779de085ee939e8
|
File details
Details for the file almeshmerge-0.1.48-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: almeshmerge-0.1.48-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 440.5 kB
- Tags: CPython 3.11, manylinux: glibc 2.24+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1af5ed148ebad3ed7d991744eee662dee6234fd86b853847e633e09b9117325a
|
|
| MD5 |
5ceb4ac1fb8913492cc1bcf216bb7c3a
|
|
| BLAKE2b-256 |
e47e60799104b04ba069173759b8c9b590a3f7829cd7bc6f6dd29852966b664a
|