@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 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
@@ -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 };