@webxr-jp/avatar-optimizer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +105 -0
- package/dist/index.d.ts +582 -0
- package/dist/index.js +2293 -0
- package/dist/index.js.map +1 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 xrift
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# @webxr-jp/avatar-optimizer
|
|
2
|
+
|
|
3
|
+
3D model optimization library for WebXR applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- VRM model loading and export
|
|
8
|
+
- Texture atlas generation for material consolidation
|
|
9
|
+
- Mesh simplification using meshoptimizer
|
|
10
|
+
- KTX2 texture compression support
|
|
11
|
+
- VRM0 to VRM1 skeleton migration utilities
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @webxr-jp/avatar-optimizer
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Peer Dependencies
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @gltf-transform/core @gltf-transform/extensions @pixiv/three-vrm @pixiv/three-vrm-materials-mtoon three
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Basic Optimization
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { loadVRM, optimizeModel, exportVRM } from '@webxr-jp/avatar-optimizer'
|
|
31
|
+
|
|
32
|
+
// Load VRM file
|
|
33
|
+
const vrmResult = await loadVRM(file)
|
|
34
|
+
if (vrmResult.isErr()) {
|
|
35
|
+
console.error(vrmResult.error)
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
const vrm = vrmResult.value
|
|
39
|
+
|
|
40
|
+
// Optimize model
|
|
41
|
+
const optimizedResult = await optimizeModel(vrm, {
|
|
42
|
+
atlas: {
|
|
43
|
+
resolution: { base: 2048, blend: 1024 },
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
if (optimizedResult.isErr()) {
|
|
47
|
+
console.error(optimizedResult.error)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
const optimizedVrm = optimizedResult.value
|
|
51
|
+
|
|
52
|
+
// Export VRM
|
|
53
|
+
const exportResult = await exportVRM(optimizedVrm)
|
|
54
|
+
if (exportResult.isErr()) {
|
|
55
|
+
console.error(exportResult.error)
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
const blob = new Blob([exportResult.value], { type: 'model/gltf-binary' })
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### With Texture Compression
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { exportVRM, UastcQuality } from '@webxr-jp/avatar-optimizer'
|
|
65
|
+
|
|
66
|
+
const exportResult = await exportVRM(vrm, {
|
|
67
|
+
textureCompression: {
|
|
68
|
+
quality: UastcQuality.Default,
|
|
69
|
+
supercompression: true,
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Mesh Simplification
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { simplifyMeshes } from '@webxr-jp/avatar-optimizer'
|
|
78
|
+
|
|
79
|
+
const result = await simplifyMeshes(vrm, {
|
|
80
|
+
targetRatio: 0.5,
|
|
81
|
+
targetError: 0.01,
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API
|
|
86
|
+
|
|
87
|
+
### Main Functions
|
|
88
|
+
|
|
89
|
+
| Function | Description |
|
|
90
|
+
| ------------------------------ | --------------------------------------- |
|
|
91
|
+
| `loadVRM(source)` | Load VRM from File, URL, or ArrayBuffer |
|
|
92
|
+
| `optimizeModel(vrm, options)` | Apply optimization pipeline |
|
|
93
|
+
| `exportVRM(vrm, options?)` | Export VRM to GLB binary |
|
|
94
|
+
| `simplifyMeshes(vrm, options)` | Reduce polygon count |
|
|
95
|
+
|
|
96
|
+
### Types
|
|
97
|
+
|
|
98
|
+
- `OptimizationOptions` - Configuration for optimization pipeline
|
|
99
|
+
- `ExportVRMOptions` - Export settings including texture compression
|
|
100
|
+
- `SimplifyOptions` - Mesh simplification parameters
|
|
101
|
+
- `TextureCompressionOptions` - KTX2 compression settings
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
import { VRM, MToonMaterial } from '@pixiv/three-vrm';
|
|
2
|
+
import { ResultAsync, Result } from 'neverthrow';
|
|
3
|
+
import { UastcQuality } from '@webxr-jp/texture-compression';
|
|
4
|
+
export { UastcQuality } from '@webxr-jp/texture-compression';
|
|
5
|
+
import { Vector2, Object3D, Mesh, Matrix3, Bone, Vector3 } from 'three';
|
|
6
|
+
import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
7
|
+
import { MToonAtlasMaterial } from '@webxr-jp/mtoon-atlas';
|
|
8
|
+
|
|
9
|
+
interface OptimizationOptions {
|
|
10
|
+
compressTextures: boolean;
|
|
11
|
+
maxTextureSize: number;
|
|
12
|
+
reduceMeshes: boolean;
|
|
13
|
+
targetPolygonCount?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* メッシュ簡略化オプション
|
|
17
|
+
*/
|
|
18
|
+
interface SimplifyOptions {
|
|
19
|
+
/**
|
|
20
|
+
* 目標頂点削減率 (0.0-1.0)
|
|
21
|
+
* 例: 0.5 = 頂点数を50%に削減
|
|
22
|
+
* @default 0.5
|
|
23
|
+
*/
|
|
24
|
+
targetRatio?: number;
|
|
25
|
+
/**
|
|
26
|
+
* 目標エラー値(0.0-1.0)
|
|
27
|
+
* 簡略化による形状変化の許容度
|
|
28
|
+
* @default 0.01
|
|
29
|
+
*/
|
|
30
|
+
targetError?: number;
|
|
31
|
+
/**
|
|
32
|
+
* 境界頂点をロックするか
|
|
33
|
+
* trueの場合、メッシュの端にある頂点は移動・削除されない
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
lockBorder?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* UV属性の重み(0.0-1.0)
|
|
39
|
+
* 高い値ほどテクスチャ座標の保護を優先
|
|
40
|
+
* @default 1.0
|
|
41
|
+
*/
|
|
42
|
+
uvWeight?: number;
|
|
43
|
+
/**
|
|
44
|
+
* 法線属性の重み(0.0-1.0)
|
|
45
|
+
* 高い値ほどシェーディングの滑らかさを優先
|
|
46
|
+
* @default 0.5
|
|
47
|
+
*/
|
|
48
|
+
normalWeight?: number;
|
|
49
|
+
/**
|
|
50
|
+
* MorphTargetを持つメッシュの処理方法
|
|
51
|
+
* - 'skip': 簡略化をスキップ
|
|
52
|
+
* - 'discard': MorphTargetを破棄して簡略化
|
|
53
|
+
* @default 'skip'
|
|
54
|
+
*/
|
|
55
|
+
morphTargetHandling?: 'skip' | 'discard';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* optimizeModel 関数のオプション
|
|
59
|
+
*/
|
|
60
|
+
interface OptimizeModelOptions {
|
|
61
|
+
/**
|
|
62
|
+
* VRM0.xからVRM1.0へのスケルトンマイグレーションを行う
|
|
63
|
+
* Y軸周り180度回転を適用してモデルの向きを+Z前向きに変更
|
|
64
|
+
*/
|
|
65
|
+
migrateVRM0ToVRM1?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* アトラス生成オプション
|
|
68
|
+
* スロットごとの解像度指定などを行う
|
|
69
|
+
*/
|
|
70
|
+
atlas?: AtlasGenerationOptions;
|
|
71
|
+
/**
|
|
72
|
+
* メッシュ簡略化オプション
|
|
73
|
+
* 設定された場合、excludedMeshes以外のメッシュを簡略化
|
|
74
|
+
*/
|
|
75
|
+
simplify?: SimplifyOptions;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* three-vrm / GLTFLoader で読み込んだ VRM ドキュメント
|
|
79
|
+
*/
|
|
80
|
+
interface ThreeVRMDocument {
|
|
81
|
+
gltf: GLTF;
|
|
82
|
+
vrm: VRM;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* テクスチャスロットの情報
|
|
86
|
+
* マテリアルごとにどのテクスチャがどのスロットで使用されているかを記録
|
|
87
|
+
*/
|
|
88
|
+
interface TextureSlotInfo {
|
|
89
|
+
slot: 'baseColor';
|
|
90
|
+
/** 当該スロットで使用されているテクスチャのリスト */
|
|
91
|
+
textures: Array<{
|
|
92
|
+
name: string;
|
|
93
|
+
width: number;
|
|
94
|
+
height: number;
|
|
95
|
+
mimeType: string;
|
|
96
|
+
materials: string[];
|
|
97
|
+
}>;
|
|
98
|
+
/** テクスチャを使用しているマテリアル数(重複なし) */
|
|
99
|
+
materialCount: number;
|
|
100
|
+
/** 総テクスチャバイト数 */
|
|
101
|
+
totalBytes: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* テクスチャスロット名の型
|
|
105
|
+
*/
|
|
106
|
+
declare const MTOON_TEXTURE_SLOTS: readonly ["map", "normalMap", "emissiveMap", "shadeMultiplyTexture", "shadingShiftTexture", "matcapTexture", "rimMultiplyTexture", "outlineWidthMultiplyTexture", "uvAnimationMaskTexture"];
|
|
107
|
+
type MToonTextureSlot = (typeof MTOON_TEXTURE_SLOTS)[number];
|
|
108
|
+
/**
|
|
109
|
+
* アトラス化対象となる1枚のテクスチャ
|
|
110
|
+
*/
|
|
111
|
+
interface AtlasTextureDescriptor {
|
|
112
|
+
/** 画像の幅(ピクセル) */
|
|
113
|
+
width: number;
|
|
114
|
+
/** 画像の高さ(ピクセル) */
|
|
115
|
+
height: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 主にUVで使用するオフセットとスケール情報
|
|
119
|
+
*/
|
|
120
|
+
interface OffsetScale {
|
|
121
|
+
offset: Vector2;
|
|
122
|
+
scale: Vector2;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* スロットごとのアトラス解像度設定
|
|
126
|
+
* 指定されていないスロットはデフォルト値(2048)を使用
|
|
127
|
+
*/
|
|
128
|
+
type SlotAtlasResolution = Partial<Record<MToonTextureSlot, number>>;
|
|
129
|
+
/**
|
|
130
|
+
* アトラス生成オプション
|
|
131
|
+
*/
|
|
132
|
+
interface AtlasGenerationOptions {
|
|
133
|
+
/**
|
|
134
|
+
* デフォルトのアトラス解像度(各辺のピクセル数)
|
|
135
|
+
* @default 2048
|
|
136
|
+
*/
|
|
137
|
+
defaultResolution?: number;
|
|
138
|
+
/**
|
|
139
|
+
* スロットごとの解像度オーバーライド
|
|
140
|
+
* 例: { map: 2048, normalMap: 1024, emissiveMap: 512 }
|
|
141
|
+
*/
|
|
142
|
+
slotResolutions?: SlotAtlasResolution;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* エラー型 (全体)
|
|
146
|
+
*/
|
|
147
|
+
type OptimizationError = {
|
|
148
|
+
type: 'ASSET_ERROR';
|
|
149
|
+
message: string;
|
|
150
|
+
} | {
|
|
151
|
+
type: 'INVALID_OPERATION';
|
|
152
|
+
message: string;
|
|
153
|
+
} | {
|
|
154
|
+
type: 'INVALID_PARAMETER';
|
|
155
|
+
message: string;
|
|
156
|
+
} | {
|
|
157
|
+
type: 'INTERNAL_ERROR';
|
|
158
|
+
message: string;
|
|
159
|
+
} | {
|
|
160
|
+
type: 'NO_MATERIALS_FOUND';
|
|
161
|
+
message: string;
|
|
162
|
+
} | {
|
|
163
|
+
type: 'PARAMETER_TEXTURE_FAILED';
|
|
164
|
+
message: string;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* VRM ロード時のエラー型
|
|
168
|
+
*/
|
|
169
|
+
type VRMLoaderError = {
|
|
170
|
+
type: 'VRM_LOAD_FAILED';
|
|
171
|
+
message: string;
|
|
172
|
+
} | {
|
|
173
|
+
type: 'INVALID_VRM';
|
|
174
|
+
message: string;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* テクスチャ圧縮オプション
|
|
178
|
+
* エクスポート時にアトラステクスチャを KTX2 形式で圧縮する
|
|
179
|
+
*/
|
|
180
|
+
interface TextureCompressionOptions {
|
|
181
|
+
/**
|
|
182
|
+
* UASTC 品質レベル (0-4)
|
|
183
|
+
* @default 2 (Default)
|
|
184
|
+
*/
|
|
185
|
+
quality?: UastcQuality;
|
|
186
|
+
/**
|
|
187
|
+
* 圧縮レベル (0-5)
|
|
188
|
+
* @default 3
|
|
189
|
+
*/
|
|
190
|
+
compressionLevel?: number;
|
|
191
|
+
/**
|
|
192
|
+
* ミップマップを生成するか
|
|
193
|
+
* @default false
|
|
194
|
+
*/
|
|
195
|
+
generateMipmaps?: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Zstandard 超圧縮を使用するか
|
|
198
|
+
* @default true
|
|
199
|
+
*/
|
|
200
|
+
supercompression?: boolean;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* VRM エクスポート時のオプション
|
|
204
|
+
*/
|
|
205
|
+
interface ExportVRMOptions {
|
|
206
|
+
/**
|
|
207
|
+
* バイナリ形式 (.vrm) で出力するか
|
|
208
|
+
* @default true
|
|
209
|
+
*/
|
|
210
|
+
binary?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* テクスチャ圧縮オプション
|
|
213
|
+
* 指定された場合、アトラステクスチャを KTX2 形式で圧縮
|
|
214
|
+
*/
|
|
215
|
+
textureCompression?: TextureCompressionOptions;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* VRM エクスポート時のエラー型
|
|
219
|
+
*/
|
|
220
|
+
type ExportVRMError = {
|
|
221
|
+
type: 'EXPORT_FAILED';
|
|
222
|
+
message: string;
|
|
223
|
+
} | {
|
|
224
|
+
type: 'INVALID_VRM';
|
|
225
|
+
message: string;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* VRM モデルのメッシュ簡略化処理
|
|
230
|
+
*
|
|
231
|
+
* excludedMeshes(表情メッシュ)を除外し、
|
|
232
|
+
* 残りのメッシュに対してmeshoptimizerによる頂点削減を適用
|
|
233
|
+
*/
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* 簡略化結果の統計情報
|
|
237
|
+
*/
|
|
238
|
+
interface SimplifyStatistics {
|
|
239
|
+
/** 処理したメッシュ数 */
|
|
240
|
+
processedMeshCount: number;
|
|
241
|
+
/** スキップしたメッシュ数(表情メッシュ、MorphTarget持ち等) */
|
|
242
|
+
skippedMeshCount: number;
|
|
243
|
+
/** 削減前の総頂点数 */
|
|
244
|
+
originalVertexCount: number;
|
|
245
|
+
/** 削減後の総頂点数 */
|
|
246
|
+
simplifiedVertexCount: number;
|
|
247
|
+
/** 削減前の総インデックス数 */
|
|
248
|
+
originalIndexCount: number;
|
|
249
|
+
/** 削減後の総インデックス数 */
|
|
250
|
+
simplifiedIndexCount: number;
|
|
251
|
+
/** 頂点削減率 */
|
|
252
|
+
vertexReductionRatio: number;
|
|
253
|
+
/** インデックス削減率 */
|
|
254
|
+
indexReductionRatio: number;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* ルートノード配下のメッシュを簡略化
|
|
258
|
+
*
|
|
259
|
+
* @param rootNode - 処理対象のルートノード
|
|
260
|
+
* @param excludedMeshes - 簡略化から除外するメッシュのSet
|
|
261
|
+
* @param options - 簡略化オプション
|
|
262
|
+
* @returns 簡略化統計情報
|
|
263
|
+
*/
|
|
264
|
+
declare function simplifyMeshes(rootNode: Object3D, excludedMeshes: Set<Mesh>, options?: SimplifyOptions): ResultAsync<SimplifyStatistics, OptimizationError>;
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Core type definitions for TexTransCoreTS
|
|
268
|
+
* テクスチャアトラス化とモデル編集に必要な型を集約
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* テクスチャパッキングの結果
|
|
273
|
+
*/
|
|
274
|
+
interface PackingLayouts {
|
|
275
|
+
/** パックされたテクスチャ情報 */
|
|
276
|
+
packed: OffsetScale[];
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* テクスチャ画像データ
|
|
280
|
+
*/
|
|
281
|
+
interface TextureImageData {
|
|
282
|
+
width: number;
|
|
283
|
+
height: number;
|
|
284
|
+
data: Uint8ClampedArray;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* スロットごとに生成されたアトラス画像
|
|
288
|
+
*/
|
|
289
|
+
interface SlotAtlasImage {
|
|
290
|
+
/** アトラス PNG などのバイナリバッファ */
|
|
291
|
+
atlasImage: Uint8Array;
|
|
292
|
+
/** アトラス幅 */
|
|
293
|
+
atlasWidth: number;
|
|
294
|
+
/** アトラス高さ */
|
|
295
|
+
atlasHeight: number;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* マテリアル単位で適用する UV 変換行列
|
|
299
|
+
* 3x3 行列を一次元配列で保持 (列優先/行優先は利用側と合意)
|
|
300
|
+
*/
|
|
301
|
+
interface MaterialPlacement {
|
|
302
|
+
/** 3x3 変換行列(9 要素) */
|
|
303
|
+
uvTransform: Matrix3;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* アトラス生成結果(ドキュメント非依存のメタデータのみ)
|
|
307
|
+
*/
|
|
308
|
+
interface AtlasBuildResult {
|
|
309
|
+
/** スロットごとに生成されたアトラス画像 */
|
|
310
|
+
atlases: SlotAtlasImage[];
|
|
311
|
+
/** 各マテリアルに適用する UV 変換行列 */
|
|
312
|
+
placements: MaterialPlacement[];
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* UV座標マッピング情報
|
|
316
|
+
*/
|
|
317
|
+
interface UVMapping {
|
|
318
|
+
/** プリミティティブのインデックス */
|
|
319
|
+
primitiveIndex: number;
|
|
320
|
+
/** マテリアルのテクスチャスロット */
|
|
321
|
+
textureSlot: string;
|
|
322
|
+
/** オリジナルのテクスチャインデックス */
|
|
323
|
+
originalTextureIndex: number;
|
|
324
|
+
/** アトラス内のノーマライズされたUV座標(min) */
|
|
325
|
+
uvMin: {
|
|
326
|
+
u: number;
|
|
327
|
+
v: number;
|
|
328
|
+
};
|
|
329
|
+
/** アトラス内のノーマライズされたUV座標(max) */
|
|
330
|
+
uvMax: {
|
|
331
|
+
u: number;
|
|
332
|
+
v: number;
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* テクスチャアトラス化の結果
|
|
337
|
+
*/
|
|
338
|
+
interface AtlasResult {
|
|
339
|
+
/** アトラス化されたドキュメント */
|
|
340
|
+
document: Document;
|
|
341
|
+
/** UV座標マッピング情報 */
|
|
342
|
+
mapping: UVMapping[];
|
|
343
|
+
/** アトラス画像のメタデータ */
|
|
344
|
+
atlasMetadata: {
|
|
345
|
+
width: number;
|
|
346
|
+
height: number;
|
|
347
|
+
textureCount: number;
|
|
348
|
+
packingEfficiency: number;
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* レンダーモード(透過分離用)
|
|
353
|
+
* - opaque: 不透明(transparent === false && alphaTest === 0)
|
|
354
|
+
* - alphaTest: MASKモード(alphaTest > 0)
|
|
355
|
+
* - transparent: 半透明(transparent === true)
|
|
356
|
+
*/
|
|
357
|
+
type RenderMode = 'opaque' | 'alphaTest' | 'transparent';
|
|
358
|
+
/**
|
|
359
|
+
* メッシュグループ(レンダーモードごとの結合結果)
|
|
360
|
+
* meshがnullの場合はexcludedMeshes専用グループ(結合メッシュなし、マテリアルのみ)
|
|
361
|
+
*/
|
|
362
|
+
interface MeshGroup {
|
|
363
|
+
/** 結合されたメッシュ(excludedMeshesのみの場合はnull) */
|
|
364
|
+
mesh: Mesh | null;
|
|
365
|
+
/** 使用されたMToonAtlasMaterial */
|
|
366
|
+
material: MToonAtlasMaterial;
|
|
367
|
+
/** アウトライン用メッシュ */
|
|
368
|
+
outlineMesh?: Mesh;
|
|
369
|
+
/** アウトライン用MToonAtlasMaterial */
|
|
370
|
+
outlineMaterial?: MToonAtlasMaterial;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* マテリアルスロット情報
|
|
374
|
+
*/
|
|
375
|
+
interface MaterialSlotInfo {
|
|
376
|
+
/** レンダーモード */
|
|
377
|
+
renderMode: RenderMode;
|
|
378
|
+
/** グループ内でのスロットインデックス */
|
|
379
|
+
slotIndex: number;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* マテリアル結合の結果
|
|
383
|
+
*/
|
|
384
|
+
interface CombinedMeshResult {
|
|
385
|
+
/** レンダーモードごとのメッシュグループ */
|
|
386
|
+
groups: Map<RenderMode, MeshGroup>;
|
|
387
|
+
/** マテリアルからスロット情報へのマッピング */
|
|
388
|
+
materialSlotIndex: Map<MToonMaterial, MaterialSlotInfo>;
|
|
389
|
+
/** 統計情報 */
|
|
390
|
+
statistics: {
|
|
391
|
+
/** 元のメッシュ数 */
|
|
392
|
+
originalMeshCount: number;
|
|
393
|
+
/** 元のマテリアル数(重複排除後) */
|
|
394
|
+
originalMaterialCount: number;
|
|
395
|
+
/** 削減されたドローコール数 */
|
|
396
|
+
reducedDrawCalls: number;
|
|
397
|
+
/** メッシュ簡略化の統計(簡略化を実行した場合のみ) */
|
|
398
|
+
simplify?: SimplifyStatistics;
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* 受け取ったThree.jsオブジェクトのツリーのメッシュ及びそのマテリアルを走査し、
|
|
404
|
+
* Three.jsの複数MToonNodeMaterialをチャンネルごとにテクスチャパッキング
|
|
405
|
+
* アトラス化したテクスチャを各マテリアルに設定する
|
|
406
|
+
* 対応するメッシュのUVをパッキング結果に基づき修正する
|
|
407
|
+
* 最後にマテリアルを統合してドローコール数を削減する
|
|
408
|
+
*
|
|
409
|
+
* @param vrm - 最適化対象のVRMオブジェクト
|
|
410
|
+
* @param options - 最適化オプション
|
|
411
|
+
* @returns 最適化結果(統合メッシュ情報を含む)
|
|
412
|
+
*/
|
|
413
|
+
declare function optimizeModel(vrm: VRM, options?: OptimizeModelOptions): ResultAsync<CombinedMeshResult, OptimizationError>;
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* VRM エクスポート機能
|
|
417
|
+
* VRM を Uint8Array (バイナリ) としてエクスポートする
|
|
418
|
+
*/
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* VRM をバイナリとしてエクスポートする
|
|
422
|
+
*
|
|
423
|
+
* @param vrm - エクスポート対象の VRM
|
|
424
|
+
* @param options - エクスポートオプション
|
|
425
|
+
* @returns ArrayBuffer (バイナリデータ) またはエラー
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```typescript
|
|
429
|
+
* const result = await exportVRM(vrm)
|
|
430
|
+
*
|
|
431
|
+
* if (result.isOk()) {
|
|
432
|
+
* // ブラウザでダウンロード
|
|
433
|
+
* const blob = new Blob([result.value], { type: 'application/octet-stream' })
|
|
434
|
+
* const url = URL.createObjectURL(blob)
|
|
435
|
+
* // ...
|
|
436
|
+
*
|
|
437
|
+
* // Node.js でファイル書き出し
|
|
438
|
+
* fs.writeFileSync('output.vrm', Buffer.from(result.value))
|
|
439
|
+
* }
|
|
440
|
+
* ```
|
|
441
|
+
*/
|
|
442
|
+
declare function exportVRM(vrm: VRM, options?: ExportVRMOptions): ResultAsync<ArrayBuffer, ExportVRMError>;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* VRM ロード機能
|
|
446
|
+
* URL / File / Blob / ArrayBuffer から VRM を読み込む
|
|
447
|
+
*/
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* VRM ソースの型
|
|
451
|
+
* URL文字列、File、Blob、ArrayBuffer を受け付ける
|
|
452
|
+
*/
|
|
453
|
+
type VRMSource = string | File | Blob | ArrayBuffer;
|
|
454
|
+
/**
|
|
455
|
+
* VRM を読み込む
|
|
456
|
+
*
|
|
457
|
+
* @param source - VRM ソース (URL文字列 / File / Blob / ArrayBuffer)
|
|
458
|
+
* @returns VRM オブジェクトまたはエラー
|
|
459
|
+
*
|
|
460
|
+
* @example
|
|
461
|
+
* ```typescript
|
|
462
|
+
* // URL から読み込み
|
|
463
|
+
* const result = await loadVRM('/path/to/model.vrm')
|
|
464
|
+
*
|
|
465
|
+
* // File から読み込み
|
|
466
|
+
* const result = await loadVRM(file)
|
|
467
|
+
*
|
|
468
|
+
* // ArrayBuffer から読み込み
|
|
469
|
+
* const result = await loadVRM(arrayBuffer)
|
|
470
|
+
* ```
|
|
471
|
+
*/
|
|
472
|
+
declare function loadVRM(source: VRMSource): ResultAsync<VRM, VRMLoaderError>;
|
|
473
|
+
|
|
474
|
+
declare class VRMExporterPlugin {
|
|
475
|
+
readonly name = "VRMC_vrm";
|
|
476
|
+
private writer;
|
|
477
|
+
private vrm;
|
|
478
|
+
private createdTailNodes;
|
|
479
|
+
constructor(writer: any);
|
|
480
|
+
setVRM(vrm: VRM): void;
|
|
481
|
+
beforeParse(input: Object3D | Object3D[]): void;
|
|
482
|
+
/**
|
|
483
|
+
* SpringBone末端ジョイントに仮想tailノードを作成
|
|
484
|
+
* three-vrmと同様に、ボーン方向に7cmのオフセットを持つ仮想ノードを追加
|
|
485
|
+
*/
|
|
486
|
+
private createVirtualTailNodes;
|
|
487
|
+
/**
|
|
488
|
+
* エクスポート後に作成した仮想tailノードをクリーンアップ
|
|
489
|
+
*/
|
|
490
|
+
cleanupTailNodes(): void;
|
|
491
|
+
afterParse(_input: any): void;
|
|
492
|
+
private exportMeta;
|
|
493
|
+
private exportHumanoid;
|
|
494
|
+
private exportExpressions;
|
|
495
|
+
private exportLookAt;
|
|
496
|
+
private exportFirstPerson;
|
|
497
|
+
/**
|
|
498
|
+
* VRMC_springBone 拡張をエクスポート
|
|
499
|
+
* three-vrm の VRMSpringBoneManager から SpringBone データを抽出
|
|
500
|
+
*/
|
|
501
|
+
private exportSpringBone;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* マイグレーションオプション
|
|
506
|
+
*/
|
|
507
|
+
interface MigrationOptions {
|
|
508
|
+
/** Humanoid Boneのセット(これらのボーンのみ回転をidentityにする) */
|
|
509
|
+
humanoidBones?: Set<Bone>;
|
|
510
|
+
/** 頂点回転をスキップ(デバッグ用) */
|
|
511
|
+
skipVertexRotation?: boolean;
|
|
512
|
+
/** ボーン位置回転をスキップ(デバッグ用) */
|
|
513
|
+
skipBoneTransform?: boolean;
|
|
514
|
+
/** bindMatrix更新をスキップ(デバッグ用) */
|
|
515
|
+
skipBindMatrix?: boolean;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* VRM0.x形式のスケルトンをVRM1.0形式に変換
|
|
519
|
+
* Y軸周り180度回転を適用してモデルの向きを+Z前向きに変更
|
|
520
|
+
*
|
|
521
|
+
* 処理内容:
|
|
522
|
+
* 1. 全メッシュの頂点位置をY軸180度回転
|
|
523
|
+
* 2. 各ボーンのワールド座標を記録し、Y軸180度回転
|
|
524
|
+
* 3. Humanoid Boneのrotationをidentityにリセット(VRM1.0仕様)
|
|
525
|
+
* - 非Humanoid Bone(髪、服など)は相対的な回転を保持
|
|
526
|
+
* 4. ルートからツリーを下りながらローカル位置を再計算
|
|
527
|
+
* 5. InverseBoneMatrix(boneInverses)を再計算
|
|
528
|
+
*
|
|
529
|
+
* @param rootNode - VRMモデルのルートノード(VRM.scene)
|
|
530
|
+
* @param options - マイグレーションオプション
|
|
531
|
+
* @returns 変換結果
|
|
532
|
+
*/
|
|
533
|
+
declare function migrateSkeletonVRM0ToVRM1(rootNode: Object3D, options?: MigrationOptions): Result<void, OptimizationError>;
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* SpringBone末端ジョイントに仮想tailノードを作成
|
|
537
|
+
* VRM1.0仕様ではjointsの最後にtailノードが必要
|
|
538
|
+
* 事前に記録したボーン方向を使用して正しい向きに仮想ノードを追加
|
|
539
|
+
*
|
|
540
|
+
* @param vrm - VRMオブジェクト
|
|
541
|
+
* @param preRecordedDirections - recordSpringBoneDirectionsで記録した方向
|
|
542
|
+
* @returns 作成された仮想tailノードの配列(クリーンアップ用)
|
|
543
|
+
*/
|
|
544
|
+
declare function createVirtualTailNodes(vrm: VRM, preRecordedDirections?: Map<Bone, Vector3>): Bone[];
|
|
545
|
+
/**
|
|
546
|
+
* SpringBoneの重力方向(gravityDir)をY軸180度回転
|
|
547
|
+
* VRM0→VRM1マイグレーション時に必要
|
|
548
|
+
*
|
|
549
|
+
* gravityDirはワールド座標系で指定されるため、
|
|
550
|
+
* モデルの向きがY軸180度回転した場合は重力方向も同様に回転する必要がある
|
|
551
|
+
*
|
|
552
|
+
* @param vrm - VRMオブジェクト
|
|
553
|
+
*/
|
|
554
|
+
declare function rotateSpringBoneGravityDirections(vrm: VRM): void;
|
|
555
|
+
/**
|
|
556
|
+
* SpringBoneコライダーのオフセットをY軸180度回転
|
|
557
|
+
* VRM0→VRM1マイグレーション時に必要
|
|
558
|
+
*
|
|
559
|
+
* コライダーはHumanoid Bone(Head等)にアタッチされており、
|
|
560
|
+
* offset/tailはローカル座標系で定義されている。
|
|
561
|
+
* マイグレーション後、Humanoid Boneの回転はidentityになるが、
|
|
562
|
+
* ローカル座標系自体がY軸180度回転しているため、
|
|
563
|
+
* コライダーのオフセットも同様に回転する必要がある。
|
|
564
|
+
*
|
|
565
|
+
* @param vrm - VRMオブジェクト
|
|
566
|
+
*/
|
|
567
|
+
declare function rotateSpringBoneColliderOffsets(vrm: VRM): void;
|
|
568
|
+
/**
|
|
569
|
+
* VRM0→VRM1マイグレーション後にSpringBone関連の調整を一括で実行
|
|
570
|
+
*
|
|
571
|
+
* 以下の処理を順番に実行:
|
|
572
|
+
* 1. 末端ジョイントに仮想tailノードを作成
|
|
573
|
+
* 2. 重力方向(gravityDir)をY軸180度回転
|
|
574
|
+
* 3. コライダーオフセットをY軸180度回転
|
|
575
|
+
* 4. SpringBoneの初期状態を再設定
|
|
576
|
+
*
|
|
577
|
+
* @param vrm - VRMオブジェクト
|
|
578
|
+
* @returns 作成された仮想tailノードの配列(クリーンアップ用)
|
|
579
|
+
*/
|
|
580
|
+
declare function migrateSpringBone(vrm: VRM): Bone[];
|
|
581
|
+
|
|
582
|
+
export { type AtlasBuildResult, type AtlasGenerationOptions, type AtlasResult, type AtlasTextureDescriptor, type ExportVRMError, type ExportVRMOptions, type MaterialPlacement, type OptimizationError, type OptimizationOptions, type OptimizeModelOptions, type PackingLayouts as PackingResult, type SimplifyOptions, type SimplifyStatistics, type SlotAtlasImage, type SlotAtlasResolution, type TextureCompressionOptions, type TextureImageData, type TextureSlotInfo, type ThreeVRMDocument, type UVMapping, VRMExporterPlugin, type VRMLoaderError, type VRMSource, createVirtualTailNodes, exportVRM, loadVRM, migrateSkeletonVRM0ToVRM1, migrateSpringBone, optimizeModel, rotateSpringBoneColliderOffsets, rotateSpringBoneGravityDirections, simplifyMeshes };
|