Metadata-Version: 2.4
Name: obj2drc
Version: 1.1.0
Summary: Generate LOD resources from OBJ for Three.js viewer with Draco compression
License: MIT
Project-URL: Repository, https://github.com/your-username/obj2drc
Project-URL: Documentation, https://github.com/your-username/obj2drc#readme
Keywords: 3d,lod,obj,draco,three.js
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: numpy

# obj2drc — OBJ 转 Draco LOD 工具

将大型 OBJ 三维模型转换为多级 LOD（Level of Detail）资源，使用 Google Draco 压缩为 `.drc` 文件，适用于 Three.js 网页查看器。

## 文件结构

```
obj2drc/
├── pyproject.toml                  # 包配置：名称、版本、依赖、命令行入口
├── requirements.txt                # Python 依赖清单（numpy）
├── README.md                       # 本文件
├── .gitignore                      # 版本控制忽略规则
│
└── obj2drc/                        # Python 源码包
    ├── __init__.py                 # 公开 API 入口，导出 obj2drc / process_all
    ├── cli.py                      # 命令行入口，定义 --pos-bits / --workers 等参数
    ├── pipeline.py                 # 核心流水线：解析→简化→分块→编码→输出
    │
    └── lodkit/                     # 底层算法库
        ├── __init__.py             # 模块导出
        ├── fast_parser.py          # OBJ 解析器（两遍扫描，支持 GB 级文件）
        └── mesh_lod.py             # 网格简化 + 空间分块
```

## 文件职责

| 文件 | 职责 |
|------|------|
| **pyproject.toml** | pip 包元数据。定义包名 `obj2drc`、依赖 `numpy`、命令行入口 `obj2drc = "obj2drc.cli:main"` |
| **requirements.txt** | 运行时依赖（`numpy>=1.20`），`pip install -r` 用 |
| **__init__.py** | 导出版本号、核心函数 `obj2drc()` 和批量处理 `process_all()` |
| **cli.py** | argparse 参数解析。接收 `input.obj`、`output_dir`、`--pos-bits`、`--workers`、`--levels` 等，调用 `pipeline.obj2drc()` |
| **pipeline.py** | 6 步流水线：①解析 OBJ → ②计算 LOD 目标面数 → ③逐级简化网格 → ④空间分块 → ⑤纹理处理 → ⑥输出 `lod_config.json` |
| **fast_parser.py** | 两遍扫描解析器：第一遍计数顶点/面数，第二遍填充预分配 numpy 数组。解析结果以 `.npy` 缓存，下次秒级加载 |
| **mesh_lod.py** | 顶点聚类简化（Vertex Clustering）+ 空间分块（Spatial Tiling）。支持 UV 坐标传播 |

## 环境要求

- **Python 3.8+**
- **numpy**（通过 `pip install -r requirements.txt` 安装）
- **draco_encoder** 命令行工具 — Draco 压缩必需

### 安装 draco_encoder

**macOS（Homebrew）：**
```bash
brew install draco
```

**Linux：**
```bash
# Ubuntu/Debian
sudo apt install draco

# Fedora/RHEL
sudo dnf install draco

# Arch Linux
sudo pacman -S draco
```

> 如果发行版源中没有 `draco` 包，请使用下方源码编译方式安装。

**Windows（vcpkg）：**
```powershell
vcpkg install draco
```

**从源码编译（通用，适用于所有平台）：**
```bash
git clone https://github.com/google/draco.git
cd draco
mkdir build && cd build
cmake .. && make
sudo make install
```

## 快速开始

```bash
# 安装 Python 依赖
pip install -r requirements.txt

# 方式一：安装包后通过 obj2drc 命令运行（推荐）
pip install .
obj2drc 输入的模型.obj ./输出目录

# 方式二：通过 Python 模块运行
python -m obj2drc.cli 输入的模型.obj ./输出目录

# 指定纹理文件
obj2drc 输入的模型.obj ./输出目录 --texture 纹理.png
```

## 命令行参数

### 基础
| 参数 | 默认 | 说明 |
|------|------|------|
| `input` | 必填 | 输入 OBJ 文件路径 |
| `output` | 必填 | 输出目录 |
| `--texture PATH` | 自动检测 | 纹理 PNG。不指定则自动在 OBJ 同目录查找 |

### LOD 控制
| 参数 | 默认 | 说明 |
|------|------|------|
| `--levels N` | 自动 | LOD 层级数（3~25，根据面数自动缩放） |
| `--no-tile` | 关闭 | 禁用空间分块。所有层级输出为单文件 |

### 编码质量
| 参数 | 默认 | 说明 |
|------|------|------|
| `--pos-bits N` | 16 | 位置量化精度 (1-31)。**核心质量参数**，越低文件越小 |
| `--compress N` | 7 | Draco 压缩级别 (0-10)。越高文件越小但编码越慢 |
| `--skip-normals` | 关闭 | 跳过法线编码。Three.js 可自动计算法线 |
| `--skip-uv` | 关闭 | 跳过 UV 编码。无纹理时可开启 |

### 性能
| 参数 | 默认 | 说明 |
|------|------|------|
| `--workers N` | 1 | 并行编码线程。0=全部 CPU，1=顺序，N=指定数 |
| `--no-procedural-tex` | 关闭 | 无纹理时跳过，不生成程序化纹理 |

## 输出结构

```
输出目录/
├── mesh_lod/                       # DRC 网格文件
│   ├── lod_0.drc                   # 最粗糙层级（面数最少）
│   ├── lod_1.drc
│   ├── ...
│   ├── lod_{N}.drc                 # 分块前最细的单文件层级
│   ├── lod_{N+1}/                  # 分块层级（30 万面以上自动分块）
│   │   ├── tile_0_0_0.drc
│   │   ├── tile_0_0_1.drc
│   │   └── ...
│   └── ...
├── three_lod/
│   └── {模型名}_texture.png         # 纹理（复制或程序生成）
└── lod_config.json                 # 元数据
```

## API 用法

```python
from obj2drc import obj2drc, process_all

# 单模型
config = obj2drc("model.obj", "./output", pos_bits=14, workers=8)

# 批量处理目录下所有 OBJ
results = process_all("models/", "data/", recursive=True, workers=4)
```
