@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/util/texture/composite.ts","../src/process/gen-atlas.ts","../src/util/texture/index.ts","../src/util/texture/packing.ts","../src/process/packing.ts","../src/util/mesh/buffer-attribute.ts","../src/util/mesh/uv.ts","../src/process/set-uv.ts","../src/util/mesh/simplify-mesh.ts","../src/process/simplify.ts","../src/util/mesh/merge-mesh.ts","../src/util/material/combine.ts","../src/util/material/index.ts","../src/util/mesh/deleter.ts","../src/util/skeleton/migrate-vrm0-to-vrm1.ts","../src/util/springbone/create-virtual-tail-nodes.ts","../src/avatar-optimizer.ts","../src/exporter/VRMExporterPlugin.ts","../src/io/export.ts","../src/io/load.ts"],"names":["SRGBColorSpace","NoColorSpace","err","ok","DataTexture","RGBAFormat","Color","Vector2","Mesh","BufferGeometry","BufferAttribute","Result","safeTry","ResultAsync","SkinnedMesh","mesh","MToonMaterial","Bone","Vector3","parentWorldMatrix","Matrix4","Scene","WebGLRenderer"],"mappings":"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","file":"index.js","sourcesContent":["import type { VRM } from '@pixiv/three-vrm'\nimport { ParameterSemanticId } from '@webxr-jp/mtoon-atlas'\nimport type { UastcQuality } from '@webxr-jp/texture-compression'\nimport {\n ColorSpace,\n NoColorSpace,\n SRGBColorSpace,\n Texture,\n TypedArray,\n Vector2,\n} from 'three'\nimport type { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'\n\n/**\n * Three.jsのImageに相当するUnion型\n * Three.js自体には含まれていないので自分で定義している\n */\nexport type ThreeImageType =\n | HTMLImageElement\n | HTMLCanvasElement\n | HTMLVideoElement\n | ImageBitmap\n | OffscreenCanvas\n | ImageData\n | { data: TypedArray; width: number; height: number }\n\nexport interface OptimizationOptions {\n compressTextures: boolean\n maxTextureSize: number\n reduceMeshes: boolean\n targetPolygonCount?: number\n}\n\n/**\n * メッシュ簡略化オプション\n */\nexport interface SimplifyOptions {\n /**\n * 目標頂点削減率 (0.0-1.0)\n * 例: 0.5 = 頂点数を50%に削減\n * @default 0.5\n */\n targetRatio?: number\n /**\n * 目標エラー値(0.0-1.0)\n * 簡略化による形状変化の許容度\n * @default 0.01\n */\n targetError?: number\n /**\n * 境界頂点をロックするか\n * trueの場合、メッシュの端にある頂点は移動・削除されない\n * @default true\n */\n lockBorder?: boolean\n /**\n * UV属性の重み(0.0-1.0)\n * 高い値ほどテクスチャ座標の保護を優先\n * @default 1.0\n */\n uvWeight?: number\n /**\n * 法線属性の重み(0.0-1.0)\n * 高い値ほどシェーディングの滑らかさを優先\n * @default 0.5\n */\n normalWeight?: number\n /**\n * MorphTargetを持つメッシュの処理方法\n * - 'skip': 簡略化をスキップ\n * - 'discard': MorphTargetを破棄して簡略化\n * @default 'skip'\n */\n morphTargetHandling?: 'skip' | 'discard'\n}\n\n/**\n * optimizeModel 関数のオプション\n */\nexport interface OptimizeModelOptions {\n /**\n * VRM0.xからVRM1.0へのスケルトンマイグレーションを行う\n * Y軸周り180度回転を適用してモデルの向きを+Z前向きに変更\n */\n migrateVRM0ToVRM1?: boolean\n /**\n * アトラス生成オプション\n * スロットごとの解像度指定などを行う\n */\n atlas?: AtlasGenerationOptions\n /**\n * メッシュ簡略化オプション\n * 設定された場合、excludedMeshes以外のメッシュを簡略化\n */\n simplify?: SimplifyOptions\n}\n\n/**\n * three-vrm / GLTFLoader で読み込んだ VRM ドキュメント\n */\nexport interface ThreeVRMDocument {\n gltf: GLTF\n vrm: VRM\n}\n\n/**\n * テクスチャスロットの情報\n * マテリアルごとにどのテクスチャがどのスロットで使用されているかを記録\n */\nexport interface TextureSlotInfo {\n slot: 'baseColor'\n /** 当該スロットで使用されているテクスチャのリスト */\n textures: Array<{\n name: string\n width: number\n height: number\n mimeType: string\n materials: string[] // このテクスチャを使用しているマテリアル名のリスト\n }>\n /** テクスチャを使用しているマテリアル数(重複なし) */\n materialCount: number\n /** 総テクスチャバイト数 */\n totalBytes: number\n}\n\n/**\n * テクスチャスロット名の型\n */\nexport const MTOON_TEXTURE_SLOTS = [\n 'map',\n 'normalMap',\n 'emissiveMap',\n 'shadeMultiplyTexture',\n 'shadingShiftTexture',\n 'matcapTexture',\n 'rimMultiplyTexture',\n 'outlineWidthMultiplyTexture',\n 'uvAnimationMaskTexture',\n] as const\nexport type MToonTextureSlot = (typeof MTOON_TEXTURE_SLOTS)[number]\n\n/**\n * テクスチャスロットごとのカラースペース設定\n * - sRGB: カラーデータを持つテクスチャ(map, emissiveMap, shadeMultiplyTexture, matcapTexture, rimMultiplyTexture)\n * - Linear/NoColorSpace: 非カラーデータ(normalMap, shadingShiftTexture, outlineWidthMultiplyTexture, uvAnimationMaskTexture)\n */\nexport const MTOON_TEXTURE_SLOT_COLOR_SPACES: Record<\n MToonTextureSlot,\n ColorSpace\n> = {\n map: SRGBColorSpace,\n normalMap: NoColorSpace,\n emissiveMap: SRGBColorSpace,\n shadeMultiplyTexture: SRGBColorSpace,\n shadingShiftTexture: NoColorSpace,\n matcapTexture: SRGBColorSpace,\n rimMultiplyTexture: SRGBColorSpace,\n outlineWidthMultiplyTexture: NoColorSpace,\n uvAnimationMaskTexture: NoColorSpace,\n}\n\n/**\n * テクスチャスロット名をキーにしたアトラス画像マップの型\n */\nexport type AtlasImageMap = Record<MToonTextureSlot, Texture>\n\n/**\n * テクスチャ組み合わせパターン\n * 各スロットに設定されているテクスチャのImage参照を保持\n */\nexport interface TextureCombinationPattern {\n /** 各スロットのImage参照(nullの場合はテクスチャなし) */\n slots: Map<MToonTextureSlot, ThreeImageType | null>\n}\n\n/**\n * 組み合わせパターンとマテリアルのマッピング情報\n */\nexport interface PatternMaterialMapping {\n /** 一意な組み合わせパターン */\n pattern: TextureCombinationPattern\n /** このパターンを使用するマテリアルのインデックス配列 */\n materialIndices: number[]\n /** パッキング用のテクスチャディスクリプタ */\n textureDescriptor: AtlasTextureDescriptor\n}\n\n/**\n * アトラス化対象となる1枚のテクスチャ\n */\nexport interface AtlasTextureDescriptor {\n /** 画像の幅(ピクセル) */\n width: number\n /** 画像の高さ(ピクセル) */\n height: number\n}\n\n/**\n * 主にUVで使用するオフセットとスケール情報\n */\nexport interface OffsetScale {\n offset: Vector2\n scale: Vector2\n}\n\n/**\n * パラメータのパッキングレイアウト定義\n * mtoon-atlas の DEFAULT_PARAMETER_LAYOUT と同じ構造\n */\nexport interface ParameterLayout {\n id: ParameterSemanticId\n texel: number\n channels: readonly ('r' | 'g' | 'b' | 'a')[]\n}\n\n/**\n * デフォルトパラメータレイアウト\n * mtoon-atlas/src/types.ts の DEFAULT_PARAMETER_LAYOUT と同一\n */\nexport const PARAMETER_LAYOUT: readonly ParameterLayout[] = [\n { id: 'baseColor', texel: 0, channels: ['r', 'g', 'b'] },\n { id: 'opacity', texel: 0, channels: ['a'] },\n { id: 'shadeColor', texel: 1, channels: ['r', 'g', 'b'] },\n { id: 'shadingShiftTextureScale', texel: 1, channels: ['a'] },\n { id: 'emissiveColor', texel: 2, channels: ['r', 'g', 'b'] },\n { id: 'emissiveIntensity', texel: 2, channels: ['a'] },\n { id: 'matcapColor', texel: 3, channels: ['r', 'g', 'b'] },\n { id: 'outlineWidth', texel: 3, channels: ['a'] },\n { id: 'outlineColor', texel: 4, channels: ['r', 'g', 'b'] },\n { id: 'outlineLightingMix', texel: 4, channels: ['a'] },\n { id: 'parametricRimColor', texel: 5, channels: ['r', 'g', 'b'] },\n { id: 'parametricRimLift', texel: 5, channels: ['a'] },\n { id: 'parametricRimFresnelPower', texel: 6, channels: ['r'] },\n { id: 'shadingToony', texel: 6, channels: ['g'] },\n { id: 'rimLightingMix', texel: 6, channels: ['b'] },\n { id: 'uvAnimationRotation', texel: 6, channels: ['a'] },\n { id: 'normalScale', texel: 7, channels: ['r', 'g'] },\n { id: 'uvAnimationScrollX', texel: 7, channels: ['b'] },\n { id: 'uvAnimationScrollY', texel: 7, channels: ['a'] },\n { id: 'shadingShift', texel: 8, channels: ['r'] },\n] as const\n\n/**\n * スロットごとのアトラス解像度設定\n * 指定されていないスロットはデフォルト値(2048)を使用\n */\nexport type SlotAtlasResolution = Partial<Record<MToonTextureSlot, number>>\n\n/**\n * アトラス生成オプション\n */\nexport interface AtlasGenerationOptions {\n /**\n * デフォルトのアトラス解像度(各辺のピクセル数)\n * @default 2048\n */\n defaultResolution?: number\n /**\n * スロットごとの解像度オーバーライド\n * 例: { map: 2048, normalMap: 1024, emissiveMap: 512 }\n */\n slotResolutions?: SlotAtlasResolution\n}\n\n/**\n * エラー型 (全体)\n */\nexport type OptimizationError =\n | { type: 'ASSET_ERROR'; message: string }\n | { type: 'INVALID_OPERATION'; message: string }\n | { type: 'INVALID_PARAMETER'; message: string }\n | { type: 'INTERNAL_ERROR'; message: string }\n | { type: 'NO_MATERIALS_FOUND'; message: string }\n | { type: 'PARAMETER_TEXTURE_FAILED'; message: string }\n\n/**\n * VRM ロード時のエラー型\n */\nexport type VRMLoaderError =\n | { type: 'VRM_LOAD_FAILED'; message: string }\n | { type: 'INVALID_VRM'; message: string }\n\n/**\n * テクスチャ圧縮オプション\n * エクスポート時にアトラステクスチャを KTX2 形式で圧縮する\n */\nexport interface TextureCompressionOptions {\n /**\n * UASTC 品質レベル (0-4)\n * @default 2 (Default)\n */\n quality?: UastcQuality\n\n /**\n * 圧縮レベル (0-5)\n * @default 3\n */\n compressionLevel?: number\n\n /**\n * ミップマップを生成するか\n * @default false\n */\n generateMipmaps?: boolean\n\n /**\n * Zstandard 超圧縮を使用するか\n * @default true\n */\n supercompression?: boolean\n}\n\n/**\n * VRM エクスポート時のオプション\n */\nexport interface ExportVRMOptions {\n /**\n * バイナリ形式 (.vrm) で出力するか\n * @default true\n */\n binary?: boolean\n\n /**\n * テクスチャ圧縮オプション\n * 指定された場合、アトラステクスチャを KTX2 形式で圧縮\n */\n textureCompression?: TextureCompressionOptions\n}\n\n/**\n * VRM エクスポート時のエラー型\n */\nexport type ExportVRMError =\n | { type: 'EXPORT_FAILED'; message: string }\n | { type: 'INVALID_VRM'; message: string }\n","import { err, ok, Result } from 'neverthrow'\nimport {\n Color,\n ColorSpace,\n DataTexture,\n DoubleSide,\n LinearFilter,\n LinearSRGBColorSpace,\n Mesh,\n MeshBasicMaterial,\n NoBlending,\n NoColorSpace,\n OrthographicCamera,\n PlaneGeometry,\n RepeatWrapping,\n RGBAFormat,\n Scene,\n SRGBColorSpace,\n Texture,\n UnsignedByteType,\n WebGLRenderer,\n WebGLRenderTarget,\n} from 'three'\nimport { OptimizationError } from '../../types'\nimport { ImageMatrixPair } from './types'\n\n/** 合成時のオプション */\nexport interface ComposeImageOptions {\n width: number\n height: number\n /** 出力テクスチャのカラースペース(デフォルト: SRGBColorSpace) */\n colorSpace?: ColorSpace\n}\n\n/**\n * Three.jsのQuadメッシュと平行投影カメラを使用してImageを合成する\n * 各レイヤーを独立したPlaneGeometryとして配置し、\n * WebGLRenderTargetにオフスクリーン描画してアトラスを生成する\n *\n * @param layers - テクスチャとUV変換行列のペア配列\n * @param options - 幅・高さ・背景色\n * @returns 合成されたアトラステクスチャ\n */\nexport function composeImagesToAtlas(\n layers: ImageMatrixPair[],\n options: ComposeImageOptions,\n): Result<Texture, OptimizationError> {\n const { width, height, colorSpace = SRGBColorSpace } = options\n\n if (width <= 0 || height <= 0) {\n return err({\n type: 'INVALID_PARAMETER',\n message: 'width, heightは正の値にしてください',\n })\n }\n\n // 1. WebGL レンダラー・シーン・カメラをセットアップ\n const renderer = createRenderer()\n const scene = new Scene()\n\n // 背景色を設定(黒)\n scene.background = new Color(0, 0, 0)\n\n // 平行投影カメラ: ピクセルパーフェクトな座標系\n const camera = new OrthographicCamera(0, 1, 1, 0, 0.1, 1000)\n camera.position.z = 10\n\n // 2. オフスクリーンレンダーターゲットを作成(透明対応)\n const renderTarget = new WebGLRenderTarget(width, height)\n\n // 3. 各レイヤーをシーンに追加\n for (const layer of layers) {\n const mesh = createLayerMesh(layer)\n scene.add(mesh)\n }\n\n // 4. WebGLRenderTarget に描画\n renderer.setRenderTarget(renderTarget)\n // 透明背景でクリア(alpha = 0)\n renderer.setClearColor(0x000000, 0)\n renderer.clear()\n renderer.render(scene, camera)\n\n // 5. ピクセルデータを読み取りテクスチャを作成\n const pixels = new Uint8Array(width * height * 4)\n renderer.readRenderTargetPixels(renderTarget, 0, 0, width, height, pixels)\n\n const tex = new DataTexture(\n pixels,\n width,\n height,\n RGBAFormat,\n UnsignedByteType,\n )\n\n tex.needsUpdate = true\n\n // 必要に応じて\n tex.magFilter = LinearFilter\n tex.minFilter = LinearFilter\n tex.wrapS = RepeatWrapping\n tex.wrapT = RepeatWrapping\n tex.colorSpace = colorSpace\n\n // 6. リソース解放\n scene.traverse((obj) => {\n if (obj instanceof Mesh) {\n obj.geometry.dispose()\n if (obj.material instanceof MeshBasicMaterial) {\n obj.material.dispose()\n }\n }\n })\n renderer.dispose()\n renderTarget.dispose()\n layers.forEach((layer) => layer.image.dispose())\n\n return ok(tex)\n}\n\n/**\n * WebGL レンダラーを作成する(オフスクリーン描画用)\n * outputColorSpace を LinearSRGBColorSpace に設定し、\n * 色空間変換を行わずピクセルデータをそのまま出力する\n */\nfunction createRenderer(): WebGLRenderer {\n const canvas = new OffscreenCanvas(1, 1) // ダミーキャンバス\n const renderer = new WebGLRenderer({\n canvas: canvas as unknown as HTMLCanvasElement,\n antialias: false,\n alpha: true,\n // premultipliedAlpha を無効化してアルファ値をそのまま保持\n premultipliedAlpha: false,\n })\n // ガンマ補正を無効化(ソーステクスチャのデータをそのまま保持)\n renderer.outputColorSpace = LinearSRGBColorSpace\n return renderer\n}\n\n/**\n * UV 変換を PlaneGeometry のワールド変換に適用したメッシュを作成\n *\n * @param layer - テクスチャと UV 変換行列\n * @returns メッシュオブジェクト\n */\nfunction createLayerMesh(layer: ImageMatrixPair): Mesh {\n const texture = layer.image\n const uvTransform = layer.uvTransform\n\n // 色空間変換を無効化(ピクセルデータをそのまま合成)\n // outputColorSpace = LinearSRGBColorSpace と組み合わせて使用\n texture.colorSpace = NoColorSpace\n\n // PlaneGeometry: デフォルトは 1x1、中心が原点\n const geometry = new PlaneGeometry()\n\n // マテリアル: テクスチャを割り当て\n // アトラスでは各テクスチャが重ならない領域に配置されるため、\n // NoBlendingでソースのRGBA値をそのまま書き込む(ブレンドなし)\n const material = new MeshBasicMaterial({\n map: texture,\n side: DoubleSide,\n blending: NoBlending,\n })\n\n const mesh = new Mesh(geometry, material)\n\n // ワールド座標での位置・スケール・回転を設定\n mesh.position.x = uvTransform.offset.x + uvTransform.scale.x * 0.5\n mesh.position.y = uvTransform.offset.y + uvTransform.scale.y * 0.5\n mesh.position.z = 0\n\n mesh.scale.x = uvTransform.scale.x\n mesh.scale.y = uvTransform.scale.y\n mesh.scale.z = 1\n\n return mesh\n}\n","import { MToonMaterial } from '@pixiv/three-vrm'\nimport { err, ok, Result, safeTry } from 'neverthrow'\nimport { OptimizationError } from '..'\nimport {\n AtlasGenerationOptions,\n AtlasImageMap,\n MTOON_TEXTURE_SLOT_COLOR_SPACES,\n MTOON_TEXTURE_SLOTS,\n MToonTextureSlot,\n OffsetScale,\n PatternMaterialMapping,\n} from '../types'\nimport { composeImagesToAtlas } from '../util/texture/composite'\nimport { ImageMatrixPair } from '../util/texture/types'\n\n/** デフォルトのアトラス解像度 */\nconst DEFAULT_ATLAS_RESOLUTION = 2048\n\n/**\n * スロットのアトラス解像度を取得\n */\nfunction getSlotResolution(\n slot: MToonTextureSlot,\n options?: AtlasGenerationOptions,\n): number {\n const defaultRes = options?.defaultResolution ?? DEFAULT_ATLAS_RESOLUTION\n return options?.slotResolutions?.[slot] ?? defaultRes\n}\n\n/**\n * テクスチャ組み合わせパターンに基づいてアトラス画像を生成\n * 各スロットごとに、一意なパターンのテクスチャのみをアトラス化\n *\n * @param materials - 全マテリアル配列\n * @param patternMappings - パターンとマテリアルのマッピング\n * @param patternPlacements - パターンごとのUV変換行列\n * @param options - アトラス生成オプション(スロットごとの解像度指定など)\n * @returns スロット名をキーにしたアトラス画像のマップ\n */\nexport function generateAtlasImagesFromPatterns(\n materials: MToonMaterial[],\n patternMappings: PatternMaterialMapping[],\n patternPlacements: OffsetScale[],\n options?: AtlasGenerationOptions,\n): Result<AtlasImageMap, OptimizationError> {\n return safeTry(function* () {\n if (patternMappings.length !== patternPlacements.length) {\n return err({\n type: 'INVALID_OPERATION',\n message: 'Pattern mappings and placements length mismatch',\n })\n }\n\n const atlasMap: Partial<AtlasImageMap> = {}\n\n for (const slot of MTOON_TEXTURE_SLOTS) {\n const layers: ImageMatrixPair[] = []\n\n // 各パターンについて、最初のマテリアルからテクスチャを取得\n for (let i = 0; i < patternMappings.length; i++) {\n const mapping = patternMappings[i]\n const placement = patternPlacements[i]\n\n // このパターンの最初のマテリアルを代表として使用\n const representativeMaterialIndex = mapping.materialIndices[0]\n const material = materials[representativeMaterialIndex]\n\n const texture = material[slot]\n if (texture) {\n layers.push({\n image: texture,\n uvTransform: placement,\n })\n }\n }\n\n const resolution = getSlotResolution(slot, options)\n const atlas = yield* composeImagesToAtlas(layers, {\n width: resolution,\n height: resolution,\n colorSpace: MTOON_TEXTURE_SLOT_COLOR_SPACES[slot],\n })\n\n atlasMap[slot] = atlas\n }\n\n return ok(atlasMap as AtlasImageMap)\n })\n}\n","import { MToonMaterial } from '@pixiv/three-vrm'\nimport { ParameterSemanticId } from '@webxr-jp/mtoon-atlas'\nimport { err, ok, Result, safeTry } from 'neverthrow'\nimport {\n Color,\n DataTexture,\n FloatType,\n NearestFilter,\n RGBAFormat,\n Vector3,\n Vector4,\n} from 'three'\nimport {\n AtlasImageMap,\n AtlasTextureDescriptor,\n MTOON_TEXTURE_SLOTS,\n OffsetScale,\n OptimizationError,\n PARAMETER_LAYOUT,\n ParameterLayout,\n} from '../../types'\nimport { composeImagesToAtlas } from './composite'\nimport { ImageMatrixPair } from './types'\n\n/**\n * null 要素を有効なテクスチャの平均寸法で埋める\n * 平均値は 2 の n 乗に丸める\n *\n * @param textures - null を含む可能性のあるテクスチャ配列\n * @returns 全て有効な値で埋められたテクスチャ配列\n */\nexport function fillNullTexturesWithAverageDimensions(\n textures: Array<AtlasTextureDescriptor | null>,\n): AtlasTextureDescriptor[] {\n // 有効なテクスチャの寸法を収集\n const validTextures = textures.filter(\n (t): t is AtlasTextureDescriptor => t !== null,\n )\n\n // 有効なテクスチャがない場合のフォールバック\n if (validTextures.length === 0) {\n return textures.map((t) => t ?? { width: 512, height: 512 })\n }\n\n // 平均幅・高さを計算\n const avgWidth =\n validTextures.reduce((sum, t) => sum + t.width, 0) / validTextures.length\n const avgHeight =\n validTextures.reduce((sum, t) => sum + t.height, 0) / validTextures.length\n\n // 平均値を 2 の n 乗に丸める\n const roundedWidth = roundToNearestPowerOfTwo(avgWidth)\n const roundedHeight = roundToNearestPowerOfTwo(avgHeight)\n\n return textures.map(\n (t) => t ?? { width: roundedWidth, height: roundedHeight },\n )\n}\n\n/**\n * 値を最も近い 2 の n 乗に丸める\n * 例: 512 -> 512, 600 -> 512, 700 -> 1024\n *\n * @param value - 丸める値\n * @returns 最も近い 2 の n 乗\n */\nfunction roundToNearestPowerOfTwo(value: number): number {\n if (value <= 0) return 512 // デフォルト値\n\n // 下の 2 の n 乗\n const lower = Math.pow(2, Math.floor(Math.log2(value)))\n // 上の 2 の n 乗\n const upper = lower * 2\n\n // より近い方を返す\n return value - lower < upper - value ? lower : upper\n}\n\n/**\n * 各チャンネル(例: MainTex, BumpMap)ごとのアトラス画像を生成する\n * 現状はMToonMaterialのみ対応\n *\n * @param materials - アトラス化対象のマテリアル配列\n * @param placements - マテリアルごとのパッキング情報配列\n * @returns スロット名をキーにしたアトラス画像のマップ\n */\nexport function generateAtlasImages(\n materials: MToonMaterial[],\n placements: OffsetScale[],\n): Result<AtlasImageMap, OptimizationError> {\n return safeTry(function* () {\n if (materials.length !== placements.length) {\n return err({\n type: 'INVALID_PARAMETER',\n message: 'Materials and packing infos length mismatch',\n })\n }\n\n const atlasMap: Partial<AtlasImageMap> = {}\n\n for (const slot of MTOON_TEXTURE_SLOTS) {\n const layers: ImageMatrixPair[] = []\n\n for (let i = 0; i < materials.length; i++) {\n const mat = materials[i]\n const placement = placements[i]\n\n const texture = mat[slot]\n if (texture) {\n layers.push({\n image: texture,\n uvTransform: placement,\n })\n }\n }\n\n atlasMap[slot] = yield* composeImagesToAtlas(layers, {\n width: 2048,\n height: 2048,\n })\n }\n\n return ok(atlasMap as AtlasImageMap)\n })\n}\n\n/**\n * マテリアル配列からパラメータテクスチャを生成\n *\n * DEFAULT_PARAMETER_LAYOUTに従って19種のパラメータをRGBAテクセルにパック\n * テクスチャフォーマット: slotCount x texelsPerSlot (RGBA32F)\n *\n * @param materials - MToonNodeMaterial配列\n * @param texelsPerSlot - スロットあたりのテクセル数(デフォルト: 8)\n * @returns DataTexture\n */\nexport function createParameterTexture(\n materials: MToonMaterial[],\n texelsPerSlot: number = 9,\n): Result<DataTexture, OptimizationError> {\n if (materials.length === 0) {\n return err({\n type: 'PARAMETER_TEXTURE_FAILED',\n message: 'No materials to pack',\n })\n }\n\n const slotCount = materials.length\n const width = texelsPerSlot\n const height = slotCount\n\n // RGBA32F テクスチャデータ(Float32Array)\n const data = new Float32Array(width * height * 4)\n\n // 各マテリアル(スロット)について処理\n for (let slotIndex = 0; slotIndex < slotCount; slotIndex++) {\n const material = materials[slotIndex]\n\n // 各パラメータをレイアウトに従ってパック\n for (const layout of PARAMETER_LAYOUT) {\n const value = extractParameterValue(material, layout.id)\n packParameterValue(data, slotIndex, layout, value, texelsPerSlot)\n }\n }\n\n // DataTextureを作成\n // パラメータテクスチャは数値データなのでバイリニア補間を無効化\n const texture = new DataTexture(data, width, height, RGBAFormat, FloatType)\n texture.minFilter = NearestFilter\n texture.magFilter = NearestFilter\n texture.needsUpdate = true\n\n return ok(texture)\n}\n\n/**\n * パラメータ値をテクスチャデータにパック\n *\n * @param data - テクスチャデータ配列\n * @param slotIndex - スロットインデックス\n * @param layout - パラメータレイアウト\n * @param value - パラメータ値\n * @param texelsPerSlot - スロットあたりのテクセル数\n */\nfunction packParameterValue(\n data: Float32Array,\n slotIndex: number,\n layout: ParameterLayout,\n value: Vector3 | Vector4 | number,\n texelsPerSlot: number,\n): void {\n const texelIndex = layout.texel\n const pixelIndex = slotIndex * texelsPerSlot + texelIndex\n const baseOffset = pixelIndex * 4\n\n // 値を配列化\n let values: number[]\n if (typeof value === 'number') {\n values = [value]\n } else if ('w' in value) {\n values = [value.x, value.y, value.z, value.w]\n } else {\n values = [value.x, value.y, value.z]\n }\n\n // チャンネルにパック\n for (let i = 0; i < layout.channels.length; i++) {\n const channel = layout.channels[i]\n const channelOffset =\n channel === 'r' ? 0 : channel === 'g' ? 1 : channel === 'b' ? 2 : 3\n data[baseOffset + channelOffset] = values[i] ?? 0\n }\n}\n\n/**\n * MToonMaterialからパラメータ値を抽出\n *\n * @param material - MToonMaterial\n * @param semanticId - パラメータのセマンティクスID\n * @returns パラメータ値(Vector3, Vector4, number のいずれか)\n */\nfunction extractParameterValue(\n material: MToonMaterial,\n semanticId: ParameterSemanticId,\n): Vector3 | Vector4 | number {\n switch (semanticId) {\n case 'baseColor':\n return colorToVector3(material.color ?? new Color(1, 1, 1))\n case 'opacity':\n return material.opacity ?? 1\n case 'shadeColor':\n return colorToVector3(material.shadeColorFactor ?? new Color(0, 0, 0))\n case 'emissiveColor':\n return colorToVector3(material.emissive ?? new Color(0, 0, 0))\n case 'emissiveIntensity':\n return material.emissiveIntensity ?? 0\n case 'shadingShift':\n // shadingShiftFactor は -1〜1 の範囲なので 0〜1 に remap\n // シェーダー側で value * 2 - 1 で復元する\n return ((material.shadingShiftFactor ?? 0) + 1) / 2\n case 'shadingShiftTextureScale':\n return material.shadingShiftTextureScale ?? 1\n case 'shadingToony':\n return material.shadingToonyFactor ?? 0.9\n case 'rimLightingMix':\n return material.rimLightingMixFactor ?? 1\n case 'matcapColor':\n return colorToVector3(material.matcapFactor ?? new Color(1, 1, 1))\n case 'outlineWidth':\n return material.outlineWidthFactor ?? 0\n case 'outlineColor':\n return colorToVector3(material.outlineColorFactor ?? new Color(0, 0, 0))\n case 'outlineLightingMix':\n return material.outlineLightingMixFactor ?? 1\n case 'parametricRimColor':\n return colorToVector3(\n material.parametricRimColorFactor ?? new Color(0, 0, 0),\n )\n case 'parametricRimLift':\n return material.parametricRimLiftFactor ?? 0\n case 'parametricRimFresnelPower':\n return material.parametricRimFresnelPowerFactor ?? 5\n case 'uvAnimationScrollX':\n return 0 // TODO: MToonMaterialのプロパティ確認\n case 'uvAnimationScrollY':\n return 0 // TODO: MToonMaterialのプロパティ確認\n case 'uvAnimationRotation':\n return 0 // TODO: MToonMaterialのプロパティ確認\n case 'normalScale':\n return new Vector4(1, 1, 0, 0) // x, y のみ使用\n default:\n return 0\n }\n}\n\n/**\n * Three.js Color を Vector3 に変換\n */\nfunction colorToVector3(color: Color): Vector3 {\n return new Vector3(color.r, color.g, color.b)\n}\n","/**\n * テクスチャパッキングアルゴリズム\n *\n * rectpack-ts ライブラリを使用して、複数のテクスチャを\n * 単一のアトラスに効率的にパッキングします。\n *\n * rectpack-ts は MaxRects (Maximal Rectangles) アルゴリズムの実装で、\n * 複数の変種を提供し、高品質なテクスチャレイアウトを生成します。\n */\n\nimport { MaxRectsBssf, Packer } from 'rectpack-ts'\nimport { Rectangle } from 'rectpack-ts/dist/src/geometry'\nimport { SORT_AREA } from 'rectpack-ts/dist/src/sorting.js'\nimport { Vector2 } from 'three'\nimport type { PackingLayouts } from '../material/types'\n\nconst ATLAS_SIZE = 2048 // ←相対値しか返さないので割となんでもいい\nconst SCALE_SEARCH_EPSILON = 0.0001\n\n/**\n * テクスチャサイズ配列をパッキング(単一ビンモード)\n *\n * rectpack-ts の MaxRects アルゴリズムを使用して、\n * 複数のテクスチャを指定されたアトラスサイズに最適に配置します。\n *\n * このモードはすべてのテクスチャを単一のアトラスに詰め込もうとします。\n * テクスチャが収まらない場合は例外をスローします。\n *\n * アルゴリズム:\n * - MaxRectsBssf (Best Short Side Fit): 最短の辺を最小化\n * - SORT_AREA: 面積で降順ソート(より大きなテクスチャから処理)\n * - rotation: true(矩形の回転を許可)\n *\n * @param sizes - テクスチャサイズの配列 { width, height }\n * @param atlasWidth - アトラスの幅(ピクセル)\n * @param atlasHeight - アトラスの高さ(ピクセル)\n * @returns パッキング結果\n * @throws テクスチャがアトラスに収まらない場合\n */\nexport function packTexturesWithMaxRects(\n sizes: Array<{ width: number; height: number }>,\n): PackingLayouts {\n if (sizes.length === 0) {\n throw new Error('No textures to pack')\n }\n\n // Packer インスタンスを作成\n // - packAlgo: MaxRectsBssf(最短辺フィット)\n // - sortAlgo: SORT_AREA(面積でソート)\n // - rotation: true(回転を許可)\n const packer = new Packer({\n packAlgo: MaxRectsBssf,\n sortAlgo: SORT_AREA,\n rotation: true,\n })\n\n // アトラスを単一のビンとして追加\n packer.addBin(ATLAS_SIZE, ATLAS_SIZE)\n\n // 各テクスチャをパッカーに追加(インデックスを rid として保存)\n sizes.forEach((size, index) => {\n packer.addRect(size.width, size.height, String(index))\n })\n\n // パッキング実行\n packer.pack()\n\n // パッキング結果を取得\n const bins = packer.binList()\n if (bins.length === 0) {\n throw new Error('Packing failed: No bins were created')\n }\n\n // 最初のビンを取得\n const bin = bins[0]\n\n // rect リストに変換(PackedTexture フォーマット)\n const packed = bin.rectangles.map((rect: Rectangle) => ({\n rid: rect.rid,\n offset: new Vector2(rect.x / bin.width, rect.y / bin.height),\n scale: new Vector2(rect.width / bin.width, rect.height / bin.height),\n }))\n\n // ridでソートして元の順序に戻す\n packed.sort((a, b) => Number(a.rid) - Number(b.rid))\n\n // すべてのテクスチャがパッキングされたか確認\n if (packed.length !== sizes.length) {\n throw new Error(\n `Packing failed: ${packed.length}/${sizes.length} textures packed. Textures do not fit in atlas.`,\n )\n }\n\n // 複数のビンが使用されていないか確認\n if (bins.length > 1) {\n throw new Error(\n `Packing failed: ${bins.length} bins required, but expected single bin. Textures do not fit in atlas.`,\n )\n }\n\n return {\n packed,\n }\n}\n\n/**\n * テクスチャをスケーリングして自動的にパッキング\n *\n * 単一のアトラスにテクスチャが収まらない場合、\n * まずは指数的に縮小して成功範囲を見つけ、\n * その後は二分探索でギリギリ収まるスケールを求めます。\n *\n * @param sizes - テクスチャサイズの配列\n * @param atlasWidth - アトラスの幅\n * @param atlasHeight - アトラスの高さ\n * @returns パッキング結果(テクスチャがダウンスケーリングされる可能性あり)\n * @throws テクスチャが 1x1 ピクセルまで縮小されても収まらない場合\n */\nexport async function packTexturesWithAutoScaling(\n sizes: Array<{ width: number; height: number }>,\n): Promise<PackingLayouts> {\n if (sizes.length === 0) {\n throw new Error('No textures to pack')\n }\n\n const attemptPack = (scale: number) => {\n const scaledSizes = scaleTextureSizes(sizes, scale)\n return packTexturesWithMaxRects(scaledSizes)\n }\n\n // まずは等倍でトライし、成功すればそのまま返す\n try {\n return attemptPack(1)\n } catch {\n // 続行してスケールを絞り込む\n }\n\n const minScaleLimit = computeMinScaleLimit(sizes)\n let lastFailedScale = 1\n let lastSuccessScale: number | null = null\n let lastSuccessResult: PackingLayouts | null = null\n\n // まずは成功するスケールを見つけるまで指数的に縮小\n let currentScale = 0.5\n for (let attempt = 0; attempt < 32; attempt++) {\n if (currentScale < minScaleLimit) {\n currentScale = minScaleLimit\n }\n\n try {\n const result = attemptPack(currentScale)\n lastSuccessScale = currentScale\n lastSuccessResult = result\n break\n } catch {\n lastFailedScale = currentScale\n if (currentScale <= minScaleLimit) {\n throw new Error(\n 'Failed to pack textures using MaxRects algorithm. Could not fit textures even after scaling down to 1x1 pixels.',\n )\n }\n currentScale *= 0.5\n }\n }\n\n if (lastSuccessScale === null || lastSuccessResult === null) {\n throw new Error(\n 'Failed to pack textures using MaxRects algorithm. Could not fit textures even after scaling down to 1x1 pixels.',\n )\n }\n\n // 高速に見つかった成功スケールがそのまま最適な場合は返す\n if (lastFailedScale <= lastSuccessScale) {\n return lastSuccessResult\n }\n\n // 失敗(大きい)スケールと成功(小さい)スケールの間で二分探索\n let low = lastSuccessScale\n let high = lastFailedScale\n for (let i = 0; i < 25; i++) {\n if (Math.abs(high - low) < SCALE_SEARCH_EPSILON) {\n break\n }\n\n const mid = (low + high) / 2\n if (mid === low || mid === high) {\n break\n }\n\n try {\n const result = attemptPack(mid)\n lastSuccessScale = mid\n lastSuccessResult = result\n low = mid\n } catch {\n high = mid\n }\n }\n\n if (lastSuccessResult === null) {\n throw new Error(\n 'Failed to pack textures using MaxRects algorithm. Could not fit textures even after scaling down to 1x1 pixels.',\n )\n }\n\n return lastSuccessResult\n}\n\nfunction scaleTextureSizes(\n originalSizes: Array<{ width: number; height: number }>,\n scaleMultiplier: number,\n): Array<{ width: number; height: number }> {\n return originalSizes.map((size) => ({\n width: Math.max(1, Math.floor(size.width * scaleMultiplier)),\n height: Math.max(1, Math.floor(size.height * scaleMultiplier)),\n }))\n}\n\nfunction computeMinScaleLimit(\n sizes: Array<{ width: number; height: number }>,\n): number {\n if (sizes.length === 0) {\n return 1\n }\n\n const maxDimension = Math.max(\n ...sizes.map((size) => Math.max(size.width, size.height)),\n )\n if (maxDimension <= 0) {\n return 1\n }\n return 1 / maxDimension\n}\n\n/**\n * テクスチャをパッキング(公開 API)\n *\n * MaxRects アルゴリズムを使用してテクスチャを自動的にパッキングします。\n * テクスチャが収まらない場合は、自動的にスケーリングして再試行します。\n *\n * @param sizes - テクスチャサイズの配列 { width, height }\n * @param atlasWidth - アトラスの幅(ピクセル)\n * @param atlasHeight - アトラスの高さ(ピクセル)\n * @returns パッキング結果\n * @throws テクスチャが 1x1 ピクセルまで縮小されても収まらない場合\n */\nexport async function packTextures(\n sizes: Array<{ width: number; height: number }>,\n): Promise<PackingLayouts> {\n return packTexturesWithAutoScaling(sizes)\n}\n","import { MToonMaterial } from '@pixiv/three-vrm'\nimport { fromSafePromise, ResultAsync } from 'neverthrow'\nimport { Texture } from 'three'\nimport {\n AtlasTextureDescriptor,\n MTOON_TEXTURE_SLOTS,\n MToonTextureSlot,\n OptimizationError,\n PatternMaterialMapping,\n TextureCombinationPattern,\n ThreeImageType,\n} from '../types'\nimport { PackingLayouts } from '../util/material/types'\nimport { fillNullTexturesWithAverageDimensions } from '../util/texture'\nimport { packTextures } from '../util/texture/packing'\n\n/**\n * 渡されたマテリアルリストからメインテクスチャの解像度一覧を取得し\n * その結果をもとにテクスチャパッキングの配置情報を生成する\n *\n * @param materials 1枚にパッキングするマテリアルのリスト\n * @params atlasSize 各アトラステクスチャの一辺の解像度 (現在は正方形固定)\n * @returns アトラステクスチャを生成するためのレイアウト情報\n */\nexport function pack(\n patternMappings: PatternMaterialMapping[],\n): ResultAsync<PackingLayouts, OptimizationError> {\n return fromSafePromise(\n (async () => {\n // パターンごとのテクスチャディスクリプタを収集\n const textureDescriptors = patternMappings.map((m) => m.textureDescriptor)\n\n // width/heightが0のものを有効なテクスチャの平均値で埋める\n const texturesToPack = fillNullTexturesWithAverageDimensions(\n textureDescriptors.map((d) => (d.width > 0 && d.height > 0 ? d : null)),\n )\n\n // テクスチャパッキングを実行(パターン数分)\n return await packTextures(texturesToPack)\n })(),\n )\n}\n\n/**\n * マテリアル配列から一意なテクスチャ組み合わせパターンを抽出し、\n * 各パターンを使用するマテリアルのインデックスをマッピング\n *\n * @param materials - MToonNodeMaterial配列\n * @returns パターンとマテリアルのマッピング配列\n */\nexport function buildPatternMaterialMappings(\n materials: MToonMaterial[],\n): PatternMaterialMapping[] {\n const mappings: PatternMaterialMapping[] = []\n\n for (let i = 0; i < materials.length; i++) {\n const material = materials[i]\n const pattern = extractTexturePattern(material)\n\n // 既存のパターンと一致するか確認\n const existingMapping = mappings.find((m) =>\n isSamePattern(m.pattern, pattern),\n )\n\n if (existingMapping) {\n // 既存パターンにマテリアルインデックスを追加\n existingMapping.materialIndices.push(i)\n } else {\n // 新しいパターンとして追加\n // テクスチャディスクリプタはmapスロットから取得(nullの場合は後で平均値で埋める)\n const mapTexture = material.map\n const textureDescriptor: AtlasTextureDescriptor =\n mapTexture && hasSize(mapTexture.image)\n ? {\n width: mapTexture.image.width,\n height: mapTexture.image.height,\n }\n : {\n width: 0,\n height: 0,\n }\n\n mappings.push({\n pattern,\n materialIndices: [i],\n textureDescriptor,\n })\n }\n }\n\n return mappings\n}\n\n/**\n * マテリアルからテクスチャ組み合わせパターンを抽出\n *\n * @param material - MToonMaterial\n * @returns テクスチャ組み合わせパターン\n */\nexport function extractTexturePattern(\n material: MToonMaterial,\n): TextureCombinationPattern {\n const slots = new Map<MToonTextureSlot, ThreeImageType | null>()\n\n for (const slot of MTOON_TEXTURE_SLOTS) {\n const texture = material[slot] as Texture<ThreeImageType>\n // テクスチャのimageオブジェクトを保持(nullの場合はnull)\n slots.set(slot, texture?.image ?? null)\n }\n\n return { slots }\n}\n\n/**\n * 2つのテクスチャ組み合わせパターンが同じか判定\n * 各スロットのimageオブジェクトの同一性で判定\n *\n * @param pattern1 - パターン1\n * @param pattern2 - パターン2\n * @returns 同じパターンの場合true\n */\nfunction isSamePattern(\n pattern1: TextureCombinationPattern,\n pattern2: TextureCombinationPattern,\n): boolean {\n for (const slot of MTOON_TEXTURE_SLOTS) {\n const img1 = pattern1.slots.get(slot) ?? null\n const img2 = pattern2.slots.get(slot) ?? null\n\n // imageオブジェクトの参照が異なる場合はfalse\n if (img1 !== img2) return false\n }\n\n return true\n}\n\n/** Textureがサイズ情報を持っているか判定するヘルパー関数 */\nfunction hasSize<T>(img: T): img is T & { width: number; height: number } {\n return (\n img != null &&\n typeof (img as Record<string, unknown>).width === 'number' &&\n typeof (img as Record<string, unknown>).height === 'number'\n )\n}\n","/**\n * BufferAttribute の安全な編集ユーティリティ\n *\n * SharedArrayBuffer や InterleavedBufferAttribute を考慮し、\n * 元のバッファを変更せず新しい BufferAttribute を返す。\n */\n\nimport { BufferAttribute, InterleavedBufferAttribute, TypedArray } from 'three'\n\n/**\n * BufferAttribute または InterleavedBufferAttribute から\n * 独立した新しい BufferAttribute を作成する\n *\n * - InterleavedBufferAttribute: データを抽出して通常の BufferAttribute に変換\n * - 通常の BufferAttribute: 配列をコピーして新しい BufferAttribute を作成\n *\n * @param attr - コピー元の属性\n * @returns 新しい独立した BufferAttribute\n */\nexport function cloneBufferAttribute(\n attr: BufferAttribute | InterleavedBufferAttribute,\n): BufferAttribute {\n const count = attr.count\n const itemSize = attr.itemSize\n const normalized = attr.normalized\n\n // 元の配列の型を判定して同じ型の配列を作成\n const TypedArrayConstructor = attr.array.constructor as new (\n length: number,\n ) => TypedArray\n const newArray = new TypedArrayConstructor(count * itemSize)\n\n // InterleavedBufferAttribute の場合は getComponent でデータを抽出\n // 通常の BufferAttribute でも同じ処理で動作する\n if (attr instanceof InterleavedBufferAttribute) {\n // InterleavedBufferAttribute: ストライドを考慮してデータを抽出\n for (let i = 0; i < count; i++) {\n for (let j = 0; j < itemSize; j++) {\n newArray[i * itemSize + j] = attr.getComponent(i, j)\n }\n }\n } else {\n // 通常の BufferAttribute: 配列を直接コピー\n // slice() を使用して SharedArrayBuffer からも安全にコピー\n const sourceArray = attr.array\n for (let i = 0; i < sourceArray.length; i++) {\n newArray[i] = sourceArray[i]\n }\n }\n\n return new BufferAttribute(newArray, itemSize, normalized)\n}\n\n/**\n * BufferAttribute を安全に編集し、新しい BufferAttribute を返す\n *\n * 元の BufferAttribute は変更されない。\n * InterleavedBufferAttribute も通常の BufferAttribute に変換される。\n *\n * @param attr - 編集元の属性\n * @param editor - 配列を編集するコールバック関数\n * @returns 編集済みの新しい BufferAttribute\n *\n * @example\n * ```typescript\n * // UV座標を変換\n * const newUvAttr = editBufferAttribute(uvAttribute, (array) => {\n * for (let i = 0; i < array.length; i += 2) {\n * array[i] = translateU + scaleU * array[i]\n * array[i + 1] = translateV + scaleV * array[i + 1]\n * }\n * })\n * geometry.setAttribute('uv', newUvAttr)\n * ```\n */\nexport function editBufferAttribute<T extends TypedArray = TypedArray>(\n attr: BufferAttribute | InterleavedBufferAttribute,\n editor: (array: T) => void,\n): BufferAttribute {\n const cloned = cloneBufferAttribute(attr)\n editor(cloned.array as T)\n cloned.needsUpdate = true\n return cloned\n}\n","/**\n * UV 座標の再マッピング実装(Three.js ベース)\n *\n * テクスチャがアトラス内で物理的に移動した分だけ、\n * モデルの UV 座標も同じ量だけ移動させる\n */\n\nimport { err, ok, Result } from 'neverthrow'\nimport { BufferGeometry, Vector2 } from 'three'\nimport { OffsetScale, OptimizationError } from '../../types'\nimport { editBufferAttribute } from './buffer-attribute'\n\nfunction wrapUV(uv: Vector2) {\n let x = uv.x\n let y = uv.y\n\n // 0-1の範囲外の場合のみラップする\n // 1.0 はそのまま 1.0 として扱う(テクスチャの端)\n if (x < 0 || x > 1) x = x - Math.floor(x)\n if (y < 0 || y > 1) y = y - Math.floor(y)\n\n return new Vector2(x, y)\n}\n\n/**\n * UV 座標を変換する共通処理\n *\n * @param uvArray - UV 配列\n * @param scaleU - U スケール係数\n * @param scaleV - V スケール係数\n * @param translateU - U トランスレート値\n * @param translateV - V トランスレート値\n * @param startIndex - 処理開始インデックス\n * @param endIndex - 処理終了インデックス(含まない)\n */\nfunction applyUVTransform(\n uvArray: Float32Array,\n scaleU: number,\n scaleV: number,\n translateU: number,\n translateV: number,\n startIndex: number = 0,\n endIndex: number = uvArray.length,\n): void {\n for (let i = startIndex; i < endIndex; i += 2) {\n const oldU = uvArray[i]\n const oldV = uvArray[i + 1]\n\n // 先に0-1範囲にラップ\n const wrapped = wrapUV(new Vector2(oldU, oldV))\n const oldUWrapped = wrapped.x\n const oldVWrapped = wrapped.y\n\n // アトラス座標への変換: newUV = translate + scale * oldUV\n const newU = translateU + scaleU * oldUWrapped\n const newV = translateV + scaleV * oldVWrapped\n uvArray[i] = newU\n uvArray[i + 1] = newV\n }\n}\n\n/**\n * BufferGeometry の UV 属性を再マッピング\n *\n * editBufferAttribute を使用して安全に新しい BufferAttribute を作成し、\n * 元のバッファを変更せずに処理する。\n *\n * @param geometry - 更新対象のジオメトリ\n * @param uvTransform - UV配置情報\n */\nexport function remapGeometryUVs(\n geometry: BufferGeometry,\n uvTransform: OffsetScale,\n): Result<void, OptimizationError> {\n // uv 属性を取得\n const uvAttribute = geometry.getAttribute('uv')\n if (!uvAttribute) {\n return err({\n type: 'ASSET_ERROR',\n message: 'UVアトリビュートが存在しません',\n })\n }\n\n if (!uvAttribute.array) {\n return err({\n type: 'ASSET_ERROR',\n message: 'UVアトリビュート配列が存在しません',\n })\n }\n if (uvAttribute.itemSize !== 2) {\n return err({\n type: 'ASSET_ERROR',\n message: 'UVアトリビュートの要素数が2ではありません',\n })\n }\n\n // editBufferAttribute で安全に編集\n const newUvAttribute = editBufferAttribute<Float32Array>(\n uvAttribute,\n (uvArray) => {\n applyUVTransform(\n uvArray,\n uvTransform.scale.x,\n uvTransform.scale.y,\n uvTransform.offset.x,\n uvTransform.offset.y,\n )\n },\n )\n\n // 新しい属性を設定\n geometry.setAttribute('uv', newUvAttribute)\n return ok()\n}\n","import { MToonMaterial } from '@pixiv/three-vrm'\nimport { Result } from 'neverthrow'\nimport { BufferAttribute, BufferGeometry, Mesh, Object3D } from 'three'\nimport { OffsetScale, OptimizationError } from '../types'\nimport { remapGeometryUVs } from '../util/mesh/uv'\n\n/**\n * GLTF/VRM フロー前提で 1 Mesh = 1 Material のみをサポートし、(ただし Outline付きMToonは例外的に複数マテリアルを許容)\n * 実装簡略化と UV 再マッピングの二重適用防止を優先する。\n * 複数マテリアルの Mesh を検出した場合はエラーを返す。\n * MToonNodeMaterial のみを対象とする。\n *\n * @param rootNode - 処理対象のルートノード\n * @param materialPlacementMap - マテリアルごとの UV 配置情報マップ\n * @returns 処理結果\n */\nexport function applyPlacementsToGeometries(\n rootNode: Object3D,\n materialPlacementMap: Map<MToonMaterial, OffsetScale>,\n): Result<void[], OptimizationError> {\n const targets = new Map<BufferGeometry, OffsetScale>()\n rootNode.traverse((obj) => {\n if (!(obj instanceof Mesh)) return\n if (!(obj.geometry instanceof BufferGeometry)) return\n\n let material: MToonMaterial | null = null\n\n if (Array.isArray(obj.material)) {\n // Outline付きMToonの場合はOutline用に複数マテリアルになっている\n // 両マテリアルが全インデックスを参照するため、同様に1つのマテリアルだけ処理すればいい。\n material = obj.material[0]\n } else if (obj.material instanceof MToonMaterial) {\n material = obj.material\n }\n\n if (!(material instanceof MToonMaterial)) {\n // @ts-ignore\n if (\n obj.material?.isMToonMaterial ||\n (Array.isArray(obj.material) && obj.material[0]?.isMToonMaterial)\n ) {\n console.warn(\n 'Found MToonMaterial-like object but instanceof failed. This indicates a dual package hazard.',\n obj.material,\n )\n }\n return\n }\n\n const placement = materialPlacementMap.get(material)\n if (!placement) {\n console.warn('No placement found for material', material)\n return\n }\n\n // UV属性のみを独立させる\n // 以前は geometry.clone() で全属性をコピーしていたが、\n // POSITION, NORMAL などの共有を維持することでエクスポートサイズを削減\n const uvAttr = obj.geometry.getAttribute('uv')\n if (uvAttr) {\n // UV属性の配列をコピーして新しいBufferAttributeを作成\n const newUvArray = new Float32Array(uvAttr.array.length)\n newUvArray.set(uvAttr.array as Float32Array)\n const newUvAttr = new BufferAttribute(\n newUvArray,\n uvAttr.itemSize,\n uvAttr.normalized,\n )\n obj.geometry.setAttribute('uv', newUvAttr)\n }\n\n targets.set(obj.geometry, placement)\n })\n\n const results = [...targets].map((target) =>\n remapGeometryUVs(target[0], target[1]),\n )\n return Result.combine(results)\n}\n","/**\n * メッシュ簡略化ユーティリティ\n *\n * meshoptimizer のsimplifyWithAttributesを使用して\n * BufferGeometryの頂点数を削減する\n */\n\nimport { MeshoptSimplifier } from 'meshoptimizer'\nimport { err, ok, Result, safeTry } from 'neverthrow'\nimport {\n BufferAttribute,\n BufferGeometry,\n InterleavedBufferAttribute,\n} from 'three'\nimport { OptimizationError, SimplifyOptions } from '../../types'\n\n/** デフォルト設定 */\nconst DEFAULT_SIMPLIFY_OPTIONS: Required<SimplifyOptions> = {\n targetRatio: 0.5,\n targetError: 0.01,\n lockBorder: true,\n uvWeight: 1.0,\n normalWeight: 0.5,\n morphTargetHandling: 'skip',\n}\n\n/**\n * meshoptimizer の初期化を待機\n */\nexport async function ensureSimplifierReady(): Promise<void> {\n await MeshoptSimplifier.ready\n}\n\n/**\n * 属性データを連続した Float32Array に変換\n */\nfunction extractAttributeData(\n attr: BufferAttribute | InterleavedBufferAttribute,\n): Float32Array {\n const count = attr.count\n const itemSize = attr.itemSize\n const result = new Float32Array(count * itemSize)\n\n for (let i = 0; i < count; i++) {\n for (let j = 0; j < itemSize; j++) {\n result[i * itemSize + j] = attr.getComponent(i, j)\n }\n }\n\n return result\n}\n\n/**\n * 単一のBufferGeometryを簡略化\n *\n * @param geometry - 簡略化対象のジオメトリ\n * @param options - 簡略化オプション\n * @returns 簡略化されたジオメトリ(新しいインスタンス)\n */\nexport function simplifyGeometry(\n geometry: BufferGeometry,\n options: SimplifyOptions = {},\n): Result<BufferGeometry, OptimizationError> {\n return safeTry(function* () {\n const opts = { ...DEFAULT_SIMPLIFY_OPTIONS, ...options }\n\n // 位置属性の取得\n const positionAttr = geometry.getAttribute('position')\n if (!positionAttr) {\n return err({\n type: 'ASSET_ERROR' as const,\n message: 'position属性が存在しません',\n })\n }\n\n const vertexCount = positionAttr.count\n\n // インデックスの取得または生成\n let indices: Uint32Array\n if (geometry.index) {\n indices = new Uint32Array(geometry.index.array)\n } else {\n // 非インデックスジオメトリの場合はインデックスを生成\n indices = new Uint32Array(vertexCount)\n for (let i = 0; i < vertexCount; i++) {\n indices[i] = i\n }\n }\n\n // 位置データの準備\n const positions = extractAttributeData(positionAttr)\n\n // 属性データの収集(法線、UV)\n const uvAttr = geometry.getAttribute('uv')\n const normalAttr = geometry.getAttribute('normal')\n\n // simplifyWithAttributes用のデータ準備\n // 属性は頂点ごとに連続して配置される必要がある\n const attributeComponents: number[] = []\n const attributeWeights: number[] = []\n\n // 法線を追加(xyz: 3成分)\n if (normalAttr) {\n attributeComponents.push(3)\n for (let i = 0; i < 3; i++) {\n attributeWeights.push(opts.normalWeight)\n }\n }\n\n // UVを追加(uv: 2成分)\n if (uvAttr) {\n attributeComponents.push(2)\n for (let i = 0; i < 2; i++) {\n attributeWeights.push(opts.uvWeight)\n }\n }\n\n // 目標インデックス数の計算(3の倍数に丸める)\n const rawTargetCount = Math.floor(indices.length * opts.targetRatio)\n const targetIndexCount = Math.max(3, Math.floor(rawTargetCount / 3) * 3)\n\n // フラグの設定\n const flags: ('LockBorder' | 'Sparse' | 'ErrorAbsolute')[] = []\n if (opts.lockBorder) {\n flags.push('LockBorder')\n }\n\n // 簡略化の実行\n let newIndices: Uint32Array\n let resultError: number\n\n if (attributeWeights.length > 0) {\n // 属性を頂点ごとに連結\n const stride = attributeWeights.length\n const attributes = new Float32Array(vertexCount * stride)\n\n for (let v = 0; v < vertexCount; v++) {\n let offset = 0\n\n // 法線\n if (normalAttr) {\n for (let j = 0; j < 3; j++) {\n attributes[v * stride + offset + j] = normalAttr.getComponent(v, j)\n }\n offset += 3\n }\n\n // UV\n if (uvAttr) {\n for (let j = 0; j < 2; j++) {\n attributes[v * stride + offset + j] = uvAttr.getComponent(v, j)\n }\n }\n }\n\n ;[newIndices, resultError] = MeshoptSimplifier.simplifyWithAttributes(\n indices,\n positions,\n 3, // position stride\n attributes,\n stride,\n attributeWeights,\n null, // vertex_lock\n targetIndexCount,\n opts.targetError,\n flags,\n )\n } else {\n ;[newIndices, resultError] = MeshoptSimplifier.simplify(\n indices,\n positions,\n 3,\n targetIndexCount,\n opts.targetError,\n flags,\n )\n }\n\n // 簡略化が実質的に行われなかった場合\n if (newIndices.length === indices.length) {\n // 元のジオメトリのクローンを返す\n return ok(geometry.clone())\n }\n\n // 新しいジオメトリの構築(使用される頂点のみを含む)\n const newGeometry = yield* rebuildGeometry(geometry, newIndices)\n\n // 簡略化エラー値をuserDataに保存\n newGeometry.userData.simplifyError = resultError\n\n return ok(newGeometry)\n })\n}\n\n/**\n * 新しいインデックスに基づいてジオメトリを再構築\n * 未使用の頂点を削除し、属性を再マッピング\n */\nfunction rebuildGeometry(\n originalGeometry: BufferGeometry,\n newIndices: Uint32Array,\n): Result<BufferGeometry, OptimizationError> {\n return safeTry(function* () {\n // 使用される頂点インデックスを収集\n const usedVertices = new Set<number>()\n for (let i = 0; i < newIndices.length; i++) {\n usedVertices.add(newIndices[i])\n }\n\n // 旧インデックス→新インデックスのマッピングを作成\n const vertexRemap = new Map<number, number>()\n const sortedIndices = Array.from(usedVertices).sort((a, b) => a - b)\n let newIndex = 0\n for (const oldIndex of sortedIndices) {\n vertexRemap.set(oldIndex, newIndex++)\n }\n\n const newVertexCount = vertexRemap.size\n\n // 新しいジオメトリを作成\n const newGeometry = new BufferGeometry()\n\n // インデックスをリマップ\n const remappedIndices = new Uint32Array(newIndices.length)\n for (let i = 0; i < newIndices.length; i++) {\n const remapped = vertexRemap.get(newIndices[i])\n if (remapped === undefined) {\n return err({\n type: 'INTERNAL_ERROR' as const,\n message: `頂点インデックスのリマップに失敗しました: ${newIndices[i]}`,\n })\n }\n remappedIndices[i] = remapped\n }\n newGeometry.setIndex(new BufferAttribute(remappedIndices, 1))\n\n // 各属性をリマップ\n for (const name of Object.keys(originalGeometry.attributes)) {\n const attr = originalGeometry.getAttribute(name)\n const itemSize = attr.itemSize\n const normalized = attr.normalized\n\n // 属性の型を判定\n let TypedArrayConstructor:\n | Float32ArrayConstructor\n | Uint16ArrayConstructor\n | Uint8ArrayConstructor\n if (name === 'skinIndex') {\n // skinIndexはUint16Array\n TypedArrayConstructor = Uint16Array\n } else if (attr.array instanceof Uint8Array) {\n TypedArrayConstructor = Uint8Array\n } else {\n TypedArrayConstructor = Float32Array\n }\n\n const newArray = new TypedArrayConstructor(newVertexCount * itemSize)\n\n for (const [oldIdx, newIdx] of vertexRemap) {\n for (let j = 0; j < itemSize; j++) {\n newArray[newIdx * itemSize + j] = attr.array[oldIdx * itemSize + j]\n }\n }\n\n const newAttr = new BufferAttribute(newArray, itemSize, normalized)\n newGeometry.setAttribute(name, newAttr)\n }\n\n // グループ(マルチマテリアル用サブメッシュ)をコピー\n // 簡略化によりインデックスが変わるため、元のグループ構造は維持できない\n // グループがある場合は全インデックスを単一グループとして設定\n if (originalGeometry.groups.length > 0) {\n newGeometry.addGroup(0, remappedIndices.length, 0)\n\n if (originalGeometry.groups.length > 1) {\n // eslint-disable-next-line no-console\n console.warn(\n `複数グループ(${originalGeometry.groups.length})を持つジオメトリは単一グループに統合されます`,\n )\n }\n }\n\n // drawRangeをリセット(全体を描画対象に)\n newGeometry.setDrawRange(0, Infinity)\n\n // バウンディングボックス/スフィアを再計算\n newGeometry.computeBoundingBox()\n newGeometry.computeBoundingSphere()\n\n return ok(newGeometry)\n })\n}\n","/**\n * VRM モデルのメッシュ簡略化処理\n *\n * excludedMeshes(表情メッシュ)を除外し、\n * 残りのメッシュに対してmeshoptimizerによる頂点削減を適用\n */\n\nimport { ResultAsync } from 'neverthrow'\nimport { Mesh, Object3D, SkinnedMesh } from 'three'\nimport { OptimizationError, SimplifyOptions } from '../types'\nimport {\n ensureSimplifierReady,\n simplifyGeometry,\n} from '../util/mesh/simplify-mesh'\n\n/**\n * 簡略化結果の統計情報\n */\nexport interface SimplifyStatistics {\n /** 処理したメッシュ数 */\n processedMeshCount: number\n /** スキップしたメッシュ数(表情メッシュ、MorphTarget持ち等) */\n skippedMeshCount: number\n /** 削減前の総頂点数 */\n originalVertexCount: number\n /** 削減後の総頂点数 */\n simplifiedVertexCount: number\n /** 削減前の総インデックス数 */\n originalIndexCount: number\n /** 削減後の総インデックス数 */\n simplifiedIndexCount: number\n /** 頂点削減率 */\n vertexReductionRatio: number\n /** インデックス削減率 */\n indexReductionRatio: number\n}\n\n/**\n * ルートノード配下のメッシュを簡略化\n *\n * @param rootNode - 処理対象のルートノード\n * @param excludedMeshes - 簡略化から除外するメッシュのSet\n * @param options - 簡略化オプション\n * @returns 簡略化統計情報\n */\nexport function simplifyMeshes(\n rootNode: Object3D,\n excludedMeshes: Set<Mesh>,\n options: SimplifyOptions = {},\n): ResultAsync<SimplifyStatistics, OptimizationError> {\n return ResultAsync.fromSafePromise(\n simplifyMeshesAsync(rootNode, excludedMeshes, options),\n )\n}\n\nasync function simplifyMeshesAsync(\n rootNode: Object3D,\n excludedMeshes: Set<Mesh>,\n options: SimplifyOptions,\n): Promise<SimplifyStatistics> {\n // meshoptimizer の初期化を待機\n await ensureSimplifierReady()\n\n const stats: SimplifyStatistics = {\n processedMeshCount: 0,\n skippedMeshCount: 0,\n originalVertexCount: 0,\n simplifiedVertexCount: 0,\n originalIndexCount: 0,\n simplifiedIndexCount: 0,\n vertexReductionRatio: 0,\n indexReductionRatio: 0,\n }\n\n const opts: SimplifyOptions = {\n morphTargetHandling: 'skip',\n ...options,\n }\n\n // メッシュを収集\n const meshesToProcess: Mesh[] = []\n rootNode.traverse((obj) => {\n if (!(obj instanceof Mesh)) return\n if (excludedMeshes.has(obj)) {\n stats.skippedMeshCount++\n return\n }\n\n // MorphTargetを持つメッシュの処理\n if (\n obj.geometry.morphAttributes &&\n Object.keys(obj.geometry.morphAttributes).length > 0\n ) {\n if (opts.morphTargetHandling === 'skip') {\n // eslint-disable-next-line no-console\n console.warn(`MorphTargetを持つメッシュをスキップしました: ${obj.name}`)\n stats.skippedMeshCount++\n return\n }\n // 'discard' の場合は続行(simplifyGeometry内でmorphAttributesは処理されない)\n }\n\n meshesToProcess.push(obj)\n })\n\n // 各メッシュを簡略化\n for (const mesh of meshesToProcess) {\n const originalVertexCount =\n mesh.geometry.getAttribute('position')?.count ?? 0\n const originalIndexCount = mesh.geometry.index?.count ?? originalVertexCount\n stats.originalVertexCount += originalVertexCount\n stats.originalIndexCount += originalIndexCount\n\n const result = simplifyGeometry(mesh.geometry, options)\n\n if (result.isErr()) {\n // eslint-disable-next-line no-console\n console.warn(\n `メッシュの簡略化に失敗しました (${mesh.name}): ${result.error.message}`,\n )\n stats.skippedMeshCount++\n stats.originalVertexCount -= originalVertexCount\n stats.originalIndexCount -= originalIndexCount\n continue\n }\n\n // ジオメトリを置き換え\n const oldGeometry = mesh.geometry\n mesh.geometry = result.value\n\n // 全ての属性バッファを更新フラグをセット(WebGLキャッシュ対策)\n for (const key of Object.keys(mesh.geometry.attributes)) {\n const attr = mesh.geometry.attributes[key]\n if (attr) {\n attr.needsUpdate = true\n }\n }\n if (mesh.geometry.index) {\n mesh.geometry.index.needsUpdate = true\n }\n\n // SkinnedMeshの場合、バインドマトリックスを再計算\n if (mesh instanceof SkinnedMesh) {\n // バインドマトリックスを再適用(スケルトンとの関連付けを維持)\n if (mesh.skeleton) {\n mesh.bind(mesh.skeleton, mesh.bindMatrix)\n }\n }\n\n // 古いジオメトリを破棄\n oldGeometry.dispose()\n\n const newVertexCount = mesh.geometry.getAttribute('position')?.count ?? 0\n const newIndexCount = mesh.geometry.index?.count ?? newVertexCount\n stats.simplifiedVertexCount += newVertexCount\n stats.simplifiedIndexCount += newIndexCount\n stats.processedMeshCount++\n }\n\n // 削減率を計算\n if (stats.originalVertexCount > 0) {\n stats.vertexReductionRatio =\n 1 - stats.simplifiedVertexCount / stats.originalVertexCount\n }\n if (stats.originalIndexCount > 0) {\n stats.indexReductionRatio =\n 1 - stats.simplifiedIndexCount / stats.originalIndexCount\n }\n\n return stats\n}\n","import { err, ok, Result } from 'neverthrow'\nimport {\n Bone,\n BufferGeometry,\n Float32BufferAttribute,\n Mesh,\n Skeleton,\n SkinnedMesh,\n} from 'three'\nimport { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js'\nimport { OptimizationError } from '../../types'\n\n/**\n * ジオメトリを結合してスロット属性を追加\n *\n * BufferGeometryUtils.mergeBufferGeometriesを使用して複数のジオメトリを\n * マージし、スロット属性を追加します。\n * SkinnedMeshが含まれる場合、ボーンインデックスのリマッピングを行い、\n * 統合されたスケルトンをuserData.skeletonに格納して返します。\n *\n * @param meshes - 結合対象のメッシュ配列\n * @param materialSlotMap - メッシュ→スロットインデックスのマップ\n * @param slotAttributeName - スロット属性名\n * @returns 結合されたBufferGeometryの配列\n */\nexport function mergeGeometriesWithSlotAttribute(\n meshes: Mesh[],\n materialSlotMap: Map<Mesh, number>,\n slotAttributeName: string,\n): Result<BufferGeometry[], OptimizationError> {\n if (meshes.length === 0) {\n return err({\n type: 'ASSET_ERROR',\n message: 'マージ対象のメッシュがありません',\n })\n }\n\n // 有効なジオメトリを持つメッシュをフィルタリング\n const validMeshes: Array<{ mesh: Mesh; geometry: BufferGeometry }> = []\n for (const mesh of meshes) {\n if (mesh.geometry instanceof BufferGeometry) {\n const vertexCount = mesh.geometry.attributes.position?.count ?? 0\n if (vertexCount > 0) {\n validMeshes.push({ mesh, geometry: mesh.geometry })\n }\n }\n }\n\n if (validMeshes.length === 0) {\n return err({\n type: 'ASSET_ERROR',\n message: '有効なジオメトリを持つメッシュがありません',\n })\n }\n\n // 全てのSkinnedMeshからボーンを収集して統合リストを作成\n const allBones: Bone[] = []\n const boneUniqueMap = new Map<string, number>() // uuid -> newIndex\n const hasSkinnedMesh = validMeshes.some(\n ({ mesh }) => mesh instanceof SkinnedMesh,\n )\n\n if (hasSkinnedMesh) {\n for (const { mesh } of validMeshes) {\n if (mesh instanceof SkinnedMesh && mesh.skeleton) {\n for (const bone of mesh.skeleton.bones) {\n if (!boneUniqueMap.has(bone.uuid)) {\n boneUniqueMap.set(bone.uuid, allBones.length)\n allBones.push(bone)\n }\n }\n }\n }\n }\n\n // 各ジオメトリをワールド座標に変換\n const transformedGeometries: BufferGeometry[] = []\n const slotData: number[] = []\n\n for (const { mesh, geometry } of validMeshes) {\n const transformedGeometry = geometry.clone()\n const vertexCount = geometry.attributes.position?.count ?? 0\n\n // SkinnedMeshの場合はbindMatrixを適用して、頂点を共通の空間(スケルトン空間)に変換\n if (mesh instanceof SkinnedMesh) {\n transformedGeometry.applyMatrix4(mesh.bindMatrix)\n\n // skinIndexのリマッピング\n if (mesh.skeleton && transformedGeometry.attributes.skinIndex) {\n const skinIndexAttr = transformedGeometry.attributes.skinIndex\n const oldBones = mesh.skeleton.bones\n\n // skinIndex属性を直接書き換える\n for (let i = 0; i < skinIndexAttr.count; i++) {\n const a = skinIndexAttr.getX(i)\n const b = skinIndexAttr.getY(i)\n const c = skinIndexAttr.getZ(i)\n const d = skinIndexAttr.getW(i)\n\n // 古いインデックス -> ボーン -> UUID -> 新しいインデックス\n // ボーンが存在しない場合(ありえないはずだが)は0にしておく\n const newA = oldBones[a]\n ? (boneUniqueMap.get(oldBones[a].uuid) ?? 0)\n : 0\n const newB = oldBones[b]\n ? (boneUniqueMap.get(oldBones[b].uuid) ?? 0)\n : 0\n const newC = oldBones[c]\n ? (boneUniqueMap.get(oldBones[c].uuid) ?? 0)\n : 0\n const newD = oldBones[d]\n ? (boneUniqueMap.get(oldBones[d].uuid) ?? 0)\n : 0\n\n skinIndexAttr.setXYZW(i, newA, newB, newC, newD)\n }\n }\n }\n // 通常のMeshの場合はワールド変換を適用\n else {\n mesh.updateMatrixWorld(true)\n transformedGeometry.applyMatrix4(mesh.matrixWorld)\n }\n\n // TODO: 顔メッシュを判別して、顔メッシュの場合はモーフターゲットを残す\n // 現状は全てのメッシュからモーフターゲットを削除\n transformedGeometry.morphAttributes = {}\n transformedGeometry.morphTargetsRelative = false\n\n transformedGeometries.push(transformedGeometry)\n\n // スロットインデックスを頂点数分追加\n const slotIndex = materialSlotMap.get(mesh) ?? 0\n for (let i = 0; i < vertexCount; i++) {\n slotData.push(slotIndex)\n }\n }\n\n // BufferGeometryUtils.mergeBufferGeometriesを使用してジオメトリをマージ\n const mergedGeometry = mergeGeometries(transformedGeometries)\n\n // 統合されたスケルトンをuserDataに保存\n if (hasSkinnedMesh) {\n mergedGeometry.userData.skeleton = new Skeleton(allBones)\n }\n\n // スロット属性を追加\n const slotArray = new Float32Array(slotData)\n mergedGeometry.setAttribute(\n slotAttributeName,\n new Float32BufferAttribute(slotArray, 1),\n )\n\n return ok([mergedGeometry])\n}\n","/**\n * MToonマテリアル結合モジュール\n *\n * 複数のMToonMaterialをレンダーモードごとにグループ化し、\n * 各グループをMToonAtlasMaterialに結合してドローコールを削減します。\n *\n * レンダーモード:\n * - opaque: 不透明(transparent === false && alphaTest === 0)\n * - alphaTest: MASKモード(alphaTest > 0)\n * - transparent: 半透明(transparent === true)\n */\n\nimport { MToonMaterial } from '@pixiv/three-vrm'\nimport type {\n AtlasedTextureSet,\n MaterialSlotAttributeConfig,\n ParameterTextureDescriptor,\n} from '@webxr-jp/mtoon-atlas'\nimport { MToonAtlasMaterial } from '@webxr-jp/mtoon-atlas'\nimport { err, ok, Result, safeTry } from 'neverthrow'\nimport { BufferGeometry, DataTexture, Mesh, SkinnedMesh } from 'three'\nimport type { OptimizationError } from '../../types'\nimport { mergeGeometriesWithSlotAttribute } from '../mesh/merge-mesh'\nimport { createParameterTexture } from '../texture'\nimport { getRenderMode } from './index'\nimport type {\n CombinedMeshResult,\n CombineMaterialOptions,\n MaterialInfo,\n MaterialSlotInfo,\n MeshGroup,\n OutlineWidthMode,\n RenderMode,\n} from './types'\n\n/**\n * デフォルトオプション\n */\nconst DEFAULT_OPTIONS: Required<CombineMaterialOptions> = {\n atlasSize: 2048,\n slotAttributeName: 'mtoonMaterialSlot',\n texelsPerSlot: 9,\n}\n\n/**\n * 複数のMToonMaterialを単一のMToonAtlasMaterialに結合\n * Meshは統合して元のマテリアル識別用の頂点アトリビュートを埋め込む\n *\n * @param materialMeshMap - 最適化対象のマテリアルと、それを利用するMeshの組のデータ\n * @param options - 結合オプション\n * @returns 結合されたメッシュと統計情報\n */\nexport function combineMToonMaterials(\n materialMeshMap: Map<MToonMaterial, Mesh[]>,\n options?: CombineMaterialOptions,\n excludedMeshes?: Set<Mesh>,\n): Result<CombinedMeshResult, OptimizationError>\n\n/**\n * MaterialInfo配列から複数のMToonMaterialを単一のMToonAtlasMaterialに結合\n * アウトライン情報を使用してアウトラインメッシュも生成\n *\n * @param materialInfos - マテリアル情報の配列(アウトライン情報を含む)\n * @param options - 結合オプション\n * @returns 結合されたメッシュと統計情報(アウトラインメッシュを含む)\n */\nexport function combineMToonMaterials(\n materialInfos: MaterialInfo[],\n options?: CombineMaterialOptions,\n excludedMeshes?: Set<Mesh>,\n): Result<CombinedMeshResult, OptimizationError>\n\nexport function combineMToonMaterials(\n input: Map<MToonMaterial, Mesh[]> | MaterialInfo[],\n options: CombineMaterialOptions = {},\n excludedMeshes?: Set<Mesh>,\n): Result<CombinedMeshResult, OptimizationError> {\n // MaterialInfo[]形式に統一\n let materialInfos: MaterialInfo[]\n if (input instanceof Map) {\n // 旧API: Map<MToonMaterial, Mesh[]>からMaterialInfo[]に変換\n materialInfos = []\n for (const [material, meshes] of input) {\n materialInfos.push({\n material,\n meshes,\n hasOutline: material.outlineWidthMode !== 'none',\n outlineWidthMode: material.outlineWidthMode as OutlineWidthMode,\n renderMode: getRenderMode(material),\n })\n }\n } else {\n materialInfos = input\n }\n\n return combineMToonMaterialsInternal(materialInfos, options, excludedMeshes)\n}\n\n/**\n * MaterialInfoをレンダーモードでグループ化\n */\nfunction groupMaterialInfoByRenderMode(\n materialInfos: MaterialInfo[],\n): Map<RenderMode, MaterialInfo[]> {\n const groups = new Map<RenderMode, MaterialInfo[]>()\n\n for (const info of materialInfos) {\n const mode = info.renderMode\n if (!groups.has(mode)) {\n groups.set(mode, [])\n }\n groups.get(mode)!.push(info)\n }\n\n return groups\n}\n\n/**\n * 単一グループの結合結果\n */\ninterface SingleGroupResult {\n mesh: Mesh | null\n material: MToonAtlasMaterial\n outlineMesh?: Mesh\n outlineMaterial?: MToonAtlasMaterial\n materialSlotIndex: Map<MToonMaterial, number>\n meshCount: number\n materialCount: number\n}\n\n/**\n * 単一グループのマテリアル結合処理\n */\nfunction processSingleGroup(\n materialInfos: MaterialInfo[],\n opts: Required<CombineMaterialOptions>,\n excludedMeshes: Set<Mesh> | undefined,\n renderMode: RenderMode,\n): Result<SingleGroupResult, OptimizationError> {\n return safeTry(function* () {\n const materials = materialInfos.map((info) => info.material)\n\n // アウトライン情報を収集\n let hasAnyOutline = false\n let outlineWidthMode: OutlineWidthMode = 'worldCoordinates'\n for (const info of materialInfos) {\n if (info.hasOutline) {\n hasAnyOutline = true\n outlineWidthMode = info.outlineWidthMode\n break\n }\n }\n\n // パラメータテクスチャ生成\n const parameterTexture = yield* createParameterTexture(\n materials,\n opts.texelsPerSlot,\n )\n\n // マテリアルとメッシュのマッピング\n const materialSlotIndex = new Map<MToonMaterial, number>()\n materials.forEach((mat, index) => {\n materialSlotIndex.set(mat, index)\n })\n\n // ジオメトリ結合用マップの構築\n const meshToSlotIndex = new Map<Mesh, number>()\n const meshesForMerge: Mesh[] = []\n\n for (const info of materialInfos) {\n const slotIndex = materialSlotIndex.get(info.material) ?? 0\n for (const mesh of info.meshes) {\n if (excludedMeshes?.has(mesh)) continue\n\n meshToSlotIndex.set(mesh, slotIndex)\n meshesForMerge.push(mesh)\n }\n }\n\n // MToonAtlasMaterialの作成(excludedMeshes用にも必要なので先に作成)\n const atlasMaterial = createMToonAtlasMaterial(\n materials[0],\n parameterTexture,\n materials.length,\n opts.texelsPerSlot,\n opts.slotAttributeName,\n renderMode,\n )\n\n // マージ対象がない場合はマテリアルのみ返す(excludedMeshes専用グループ)\n if (meshesForMerge.length === 0) {\n return ok({\n mesh: null,\n material: atlasMaterial,\n outlineMesh: undefined,\n outlineMaterial: undefined,\n materialSlotIndex,\n meshCount: 0,\n materialCount: materials.length,\n })\n }\n\n // マテリアルスロットアトリビュートを追加してジオメトリ結合\n const mergedGeometries = yield* mergeGeometriesWithSlotAttribute(\n meshesForMerge,\n meshToSlotIndex,\n opts.slotAttributeName,\n )\n const mergedGeometry = mergedGeometries[0]\n\n // 結合メッシュの作成\n const { mesh: combinedMesh } = createCombinedMesh(\n mergedGeometry,\n atlasMaterial,\n meshesForMerge,\n `CombinedMToonMesh_${renderMode}`,\n )\n\n // アウトラインメッシュの作成\n let outlineMesh: Mesh | undefined\n let outlineMaterial: MToonAtlasMaterial | undefined\n\n if (hasAnyOutline) {\n outlineMaterial = atlasMaterial.createOutlineMaterial(\n outlineWidthMode === 'screenCoordinates'\n ? 'screenCoordinates'\n : 'worldCoordinates',\n )\n\n const outlineResult = createCombinedMesh(\n mergedGeometry,\n outlineMaterial,\n meshesForMerge,\n `CombinedMToonMesh_${renderMode}_Outline`,\n )\n outlineMesh = outlineResult.mesh\n outlineMesh.renderOrder = combinedMesh.renderOrder - 1\n }\n\n return ok({\n mesh: combinedMesh,\n material: atlasMaterial,\n outlineMesh,\n outlineMaterial,\n materialSlotIndex,\n meshCount: meshesForMerge.length,\n materialCount: materials.length,\n })\n })\n}\n\n/**\n * 結合メッシュを作成\n */\nfunction createCombinedMesh(\n geometry: BufferGeometry,\n material: MToonAtlasMaterial,\n sourceMeshes: Mesh[],\n name: string,\n): { mesh: Mesh; firstSkinnedMesh: SkinnedMesh | undefined } {\n const firstSkinnedMesh = sourceMeshes.find(\n (mesh): mesh is SkinnedMesh => mesh instanceof SkinnedMesh,\n )\n\n let mesh: Mesh\n if (firstSkinnedMesh) {\n const skinnedMesh = new SkinnedMesh(geometry, material)\n skinnedMesh.name = name\n\n if (geometry.userData.skeleton) {\n const skeleton = geometry.userData.skeleton\n const identityMatrix = firstSkinnedMesh.matrixWorld.clone().identity()\n skinnedMesh.bind(skeleton, identityMatrix)\n } else if (firstSkinnedMesh.skeleton) {\n const identityMatrix = firstSkinnedMesh.matrixWorld.clone().identity()\n skinnedMesh.bind(firstSkinnedMesh.skeleton, identityMatrix)\n }\n\n mesh = skinnedMesh\n } else {\n mesh = new Mesh(geometry, material)\n mesh.name = name\n }\n\n return { mesh, firstSkinnedMesh }\n}\n\n/**\n * 内部実装: MaterialInfo配列を処理(レンダーモードごとにグループ化)\n */\nfunction combineMToonMaterialsInternal(\n materialInfos: MaterialInfo[],\n options: CombineMaterialOptions,\n excludedMeshes?: Set<Mesh>,\n): Result<CombinedMeshResult, OptimizationError> {\n return safeTry(function* () {\n const opts = { ...DEFAULT_OPTIONS, ...options }\n\n // レンダーモードでグループ化\n const groupedInfos = groupMaterialInfoByRenderMode(materialInfos)\n\n // 各グループを処理\n const groups = new Map<RenderMode, MeshGroup>()\n const materialSlotIndex = new Map<MToonMaterial, MaterialSlotInfo>()\n\n let totalMeshCount = 0\n let totalMaterialCount = 0\n\n // レンダーモードの処理順序(描画順に影響)\n const renderModeOrder: RenderMode[] = ['opaque', 'alphaTest', 'transparent']\n\n for (const renderMode of renderModeOrder) {\n const infos = groupedInfos.get(renderMode)\n if (!infos || infos.length === 0) continue\n\n const result = yield* processSingleGroup(\n infos,\n opts,\n excludedMeshes,\n renderMode,\n )\n\n groups.set(renderMode, {\n mesh: result.mesh,\n material: result.material,\n outlineMesh: result.outlineMesh,\n outlineMaterial: result.outlineMaterial,\n })\n\n // マテリアルスロット情報を統合\n for (const [mat, slotIndex] of result.materialSlotIndex) {\n materialSlotIndex.set(mat, { renderMode, slotIndex })\n }\n\n totalMeshCount += result.meshCount\n totalMaterialCount += result.materialCount\n }\n\n if (groups.size === 0) {\n return err({\n type: 'ASSET_ERROR',\n message: 'マージ対象のメッシュがありません',\n })\n }\n\n // 結果のドローコール数を計算\n // meshが存在するグループにつき1ドローコール + アウトラインがあれば+1\n let resultDrawCalls = 0\n for (const group of groups.values()) {\n if (group.mesh) resultDrawCalls += 1\n if (group.outlineMesh) resultDrawCalls += 1\n }\n\n return ok({\n groups,\n materialSlotIndex,\n statistics: {\n originalMeshCount: totalMeshCount,\n originalMaterialCount: totalMaterialCount,\n reducedDrawCalls: totalMaterialCount - resultDrawCalls,\n },\n })\n })\n}\n\n/**\n * MToonAtlasMaterialを作成\n *\n * 代表マテリアルのアトラス化されたテクスチャを使用\n * パラメータテクスチャを設定\n */\nfunction createMToonAtlasMaterial(\n representativeMaterial: MToonMaterial,\n parameterTexture: DataTexture,\n slotCount: number,\n texelsPerSlot: number,\n slotAttributeName: string,\n renderMode: RenderMode,\n): MToonAtlasMaterial {\n // アトラス化されたテクスチャセットを構築\n const atlasedTextures: AtlasedTextureSet = {}\n\n // 代表マテリアルからアトラス化テクスチャを取得\n if (representativeMaterial.map) {\n atlasedTextures.baseColor = representativeMaterial.map\n }\n if (representativeMaterial.shadeMultiplyTexture) {\n atlasedTextures.shade = representativeMaterial.shadeMultiplyTexture\n }\n if (representativeMaterial.shadingShiftTexture) {\n atlasedTextures.shadingShift = representativeMaterial.shadingShiftTexture\n }\n if (representativeMaterial.normalMap) {\n atlasedTextures.normal = representativeMaterial.normalMap\n }\n if (representativeMaterial.emissiveMap) {\n atlasedTextures.emissive = representativeMaterial.emissiveMap\n }\n if (representativeMaterial.matcapTexture) {\n atlasedTextures.matcap = representativeMaterial.matcapTexture\n }\n if (representativeMaterial.rimMultiplyTexture) {\n atlasedTextures.rim = representativeMaterial.rimMultiplyTexture\n }\n if (representativeMaterial.uvAnimationMaskTexture) {\n atlasedTextures.uvAnimationMask =\n representativeMaterial.uvAnimationMaskTexture\n }\n\n // パラメータテクスチャディスクリプタを構築\n const parameterTextureDescriptor: ParameterTextureDescriptor = {\n texture: parameterTexture,\n slotCount,\n texelsPerSlot,\n atlasedTextures,\n }\n\n // スロット属性設定\n const slotAttribute: MaterialSlotAttributeConfig = {\n name: slotAttributeName,\n description: 'Material slot index for instancing',\n }\n\n // MToonAtlasMaterialを作成\n const material = new MToonAtlasMaterial({\n parameterTexture: parameterTextureDescriptor,\n slotAttribute,\n })\n\n // レンダーモードに応じた設定\n if (renderMode === 'transparent') {\n material.transparent = true\n material.depthWrite = false\n } else if (renderMode === 'alphaTest') {\n material.transparent = false\n material.alphaTest = representativeMaterial.alphaTest\n } else {\n material.transparent = false\n }\n\n return material\n}\n","/**\n * Core atlas builder\n *\n * マテリアル記述子とテクスチャスロットごとのアトラス画像、\n * そしてマテリアル単位の UV 変換行列を生成する責務を持つ。\n */\n\nimport { MToonMaterial } from '@pixiv/three-vrm'\nimport { err, ok, Result } from 'neverthrow'\nimport { Mesh, Object3D } from 'three'\nimport { AtlasImageMap, OptimizationError } from '../../types'\n\n// マテリアル結合のエクスポート\nexport { combineMToonMaterials } from './combine'\nexport type {\n CombinedMeshResult,\n CombineMaterialOptions,\n MaterialInfo,\n MaterialSlotInfo,\n MeshGroup,\n OutlineWidthMode,\n RenderMode,\n} from './types'\n\n/**\n * MToonMaterialのレンダーモードを判定\n * - transparent: true → 'transparent'\n * - alphaTest > 0 → 'alphaTest'\n * - それ以外 → 'opaque'\n */\nexport function getRenderMode(\n material: MToonMaterial,\n): import('./types').RenderMode {\n if (material.transparent) return 'transparent'\n if (material.alphaTest > 0) return 'alphaTest'\n return 'opaque'\n}\n\n/**\n * アトラス化したテクスチャ群をマテリアルにアサインする\n *\n * @param material 対象のマテリアル\n * @param atlasMap\n */\nexport function assignAtlasTexturesToMaterial(\n material: MToonMaterial,\n atlasMap: AtlasImageMap,\n): void {\n if (atlasMap.map) material.map = atlasMap.map\n if (atlasMap.normalMap) material.normalMap = atlasMap.normalMap\n if (atlasMap.emissiveMap) material.emissiveMap = atlasMap.emissiveMap\n if (atlasMap.shadeMultiplyTexture)\n material.shadeMultiplyTexture = atlasMap.shadeMultiplyTexture\n if (atlasMap.shadingShiftTexture)\n material.shadingShiftTexture = atlasMap.shadingShiftTexture\n // MatCapはUV非依存なのでスキップ\n if (atlasMap.rimMultiplyTexture)\n material.rimMultiplyTexture = atlasMap.rimMultiplyTexture\n if (atlasMap.outlineWidthMultiplyTexture)\n material.outlineWidthMultiplyTexture = atlasMap.outlineWidthMultiplyTexture\n if (atlasMap.uvAnimationMaskTexture)\n material.uvAnimationMaskTexture = atlasMap.uvAnimationMaskTexture\n}\n\n/**\n * Three.jsのノードを再帰的に探索してMeshを検索し\n * マテリアルとそれに対応するメッシュのMapを返す\n *\n * @param rootNode 探索を開始するNode\n * @returns マテリアルをキー、メッシュの配列を値とするMap\n * @deprecated getMToonMaterialInfoFromObject3Dを使用してください\n */\nexport function getMToonMaterialsWithMeshesFromObject3D(\n rootNode: Object3D,\n): Result<Map<MToonMaterial, Mesh[]>, OptimizationError> {\n const result = getMToonMaterialInfoFromObject3D(rootNode)\n if (result.isErr()) return err(result.error)\n\n const materialMeshMap = new Map<MToonMaterial, Mesh[]>()\n for (const info of result.value) {\n materialMeshMap.set(info.material, info.meshes)\n }\n return ok(materialMeshMap)\n}\n\n/**\n * Three.jsのノードを再帰的に探索してMeshを検索し\n * マテリアル情報(アウトライン情報を含む)のリストを返す\n *\n * @param rootNode 探索を開始するNode\n * @returns マテリアル情報の配列\n */\nexport function getMToonMaterialInfoFromObject3D(\n rootNode: Object3D,\n): Result<import('./types').MaterialInfo[], OptimizationError> {\n const meshes: Mesh[] = []\n rootNode.traverse((obj) => {\n if (obj instanceof Mesh) {\n meshes.push(obj)\n }\n })\n\n // マテリアルごとの情報を収集\n const materialInfoMap = new Map<\n MToonMaterial,\n {\n meshes: Mesh[]\n hasOutline: boolean\n outlineWidthMode: import('./types').OutlineWidthMode\n renderMode: import('./types').RenderMode\n }\n >()\n\n for (const mesh of meshes) {\n if (Array.isArray(mesh.material)) {\n // three-vrmで読み込んだモデルのMToonにおいてMaterialが配列になるのはOutlineMeshのみ\n // [0]が通常マテリアル、[1]がアウトライン用マテリアル(isOutline=true)\n if (mesh.material.length === 0) continue\n if (!(mesh.material[0] instanceof MToonMaterial)) continue\n\n const material = mesh.material[0] as MToonMaterial\n\n // アウトライン情報を取得\n const hasOutline = material.outlineWidthMode !== 'none'\n const outlineWidthMode =\n material.outlineWidthMode as import('./types').OutlineWidthMode\n\n if (!materialInfoMap.has(material)) {\n materialInfoMap.set(material, {\n meshes: [],\n hasOutline,\n outlineWidthMode,\n renderMode: getRenderMode(material),\n })\n }\n materialInfoMap.get(material)!.meshes.push(mesh)\n } else if (mesh.material instanceof MToonMaterial) {\n const material = mesh.material as MToonMaterial\n\n // アウトライン情報を取得\n const hasOutline = material.outlineWidthMode !== 'none'\n const outlineWidthMode =\n material.outlineWidthMode as import('./types').OutlineWidthMode\n\n if (!materialInfoMap.has(material)) {\n materialInfoMap.set(material, {\n meshes: [],\n hasOutline,\n outlineWidthMode,\n renderMode: getRenderMode(material),\n })\n }\n materialInfoMap.get(material)!.meshes.push(mesh)\n }\n }\n\n if (materialInfoMap.size === 0) {\n return err({\n type: 'ASSET_ERROR',\n message: 'MToonMaterialがありません',\n })\n }\n\n // MaterialInfo配列に変換\n const result: import('./types').MaterialInfo[] = []\n for (const [material, info] of materialInfoMap) {\n result.push({\n material,\n meshes: info.meshes,\n hasOutline: info.hasOutline,\n outlineWidthMode: info.outlineWidthMode,\n renderMode: info.renderMode,\n })\n }\n\n return ok(result)\n}\n","import { Material, Mesh } from 'three'\n\n/**\n * Mesh と関連するリソース(Material、Geometry)を削除してメモリを解放します。\n * @param mesh - 削除対象の Mesh\n * @param scene - Mesh が追加されているシーン\n */\nexport function deleteMesh(mesh: Mesh): void {\n // Material\n if (Array.isArray(mesh.material)) {\n mesh.material.forEach((m: Material) => m.dispose())\n } else {\n mesh.material.dispose()\n }\n\n // Geometry\n // 本当はBufferAttributeが共有されていないか確認すべき\n mesh.geometry.dispose()\n}\n","import { err, ok, Result, safeTry } from 'neverthrow'\nimport {\n Bone,\n BufferAttribute,\n InterleavedBufferAttribute,\n Matrix4,\n Object3D,\n Quaternion,\n Skeleton,\n SkinnedMesh,\n Vector3,\n} from 'three'\nimport { OptimizationError } from '../../types'\nimport { editBufferAttribute } from '../mesh/buffer-attribute'\n\n/**\n * マイグレーションオプション\n */\nexport interface MigrationOptions {\n /** Humanoid Boneのセット(これらのボーンのみ回転をidentityにする) */\n humanoidBones?: Set<Bone>\n /** 頂点回転をスキップ(デバッグ用) */\n skipVertexRotation?: boolean\n /** ボーン位置回転をスキップ(デバッグ用) */\n skipBoneTransform?: boolean\n /** bindMatrix更新をスキップ(デバッグ用) */\n skipBindMatrix?: boolean\n}\n\n/**\n * VRM0.x形式のスケルトンをVRM1.0形式に変換\n * Y軸周り180度回転を適用してモデルの向きを+Z前向きに変更\n *\n * 処理内容:\n * 1. 全メッシュの頂点位置をY軸180度回転\n * 2. 各ボーンのワールド座標を記録し、Y軸180度回転\n * 3. Humanoid Boneのrotationをidentityにリセット(VRM1.0仕様)\n * - 非Humanoid Bone(髪、服など)は相対的な回転を保持\n * 4. ルートからツリーを下りながらローカル位置を再計算\n * 5. InverseBoneMatrix(boneInverses)を再計算\n *\n * @param rootNode - VRMモデルのルートノード(VRM.scene)\n * @param options - マイグレーションオプション\n * @returns 変換結果\n */\nexport function migrateSkeletonVRM0ToVRM1(\n rootNode: Object3D,\n options: MigrationOptions = {},\n): Result<void, OptimizationError> {\n return safeTry(function* () {\n // 1. 全SkinnedMeshを収集\n const skinnedMeshes: SkinnedMesh[] = []\n rootNode.traverse((obj) => {\n if (obj instanceof SkinnedMesh) {\n skinnedMeshes.push(obj)\n }\n })\n\n if (skinnedMeshes.length === 0) {\n return err({\n type: 'ASSET_ERROR',\n message: 'SkinnedMeshが見つかりません',\n })\n }\n\n // 2. 各メッシュの頂点位置をY軸180度回転\n // 新しいアプローチ: 全BufferAttributeを収集し、ArrayBufferごとに1回だけ回転を適用\n // これにより、BufferAttributeの関係を気にせず、各ArrayBufferを確実に1回だけ処理できる\n if (!options.skipVertexRotation) {\n rotateAllVertexBuffers(skinnedMeshes)\n }\n\n // 3. 全ボーンのワールド座標を記録(重複排除)\n // 複数のスケルトンが同じボーンを共有している場合があるため、\n // 先にすべてのボーンの座標を記録してから変換を適用する\n if (!options.skipBoneTransform) {\n const allBonePositions = new Map<Bone, Vector3>()\n const processedSkeletons = new Set<Skeleton>()\n\n // 4. すべてのスケルトンからボーン座標を収集\n for (const mesh of skinnedMeshes) {\n const skeleton = mesh.skeleton\n if (!skeleton || processedSkeletons.has(skeleton)) continue\n processedSkeletons.add(skeleton)\n\n const positions = recordBoneWorldPositions(skeleton)\n for (const [bone, pos] of positions) {\n if (!allBonePositions.has(bone)) {\n allBonePositions.set(bone, pos)\n }\n }\n }\n\n // 5. 座標をY軸180度回転\n const rotatedPositions = rotateBonePositions(allBonePositions)\n\n // 6. 全ボーンから真のルートボーン(親がBoneでないもの)を特定\n // VRMでは各SkinnedMesh.skeleton.bonesは使用するボーンのみを含むが、\n // 実際のボーン階層は1つなので、全ボーンを走査して真のルートを見つける\n const allRootBones = new Set<Bone>()\n for (const bone of allBonePositions.keys()) {\n // 親を辿って真のルートを見つける\n let current: Bone = bone\n while (current.parent instanceof Bone) {\n current = current.parent\n }\n allRootBones.add(current)\n }\n\n if (allRootBones.size === 0) {\n return err({\n type: 'ASSET_ERROR',\n message: 'ルートボーンが見つかりません',\n })\n }\n\n // 7. 各ルートボーンからボーン変換を再構築\n for (const rootBone of allRootBones) {\n rebuildBoneTransforms(rootBone, rotatedPositions, options.humanoidBones)\n }\n\n // 8. すべてのスケルトンのInverseBoneMatrixを再計算\n processedSkeletons.forEach((skeleton) => {\n recalculateBoneInverses(skeleton)\n })\n }\n\n // 9. bindMatrixの更新\n if (!options.skipBindMatrix) {\n for (const mesh of skinnedMeshes) {\n mesh.skeleton.calculateInverses()\n }\n }\n\n return ok(undefined)\n })\n}\n\n/**\n * 全SkinnedMeshの頂点バッファにY軸180度回転を適用\n *\n * editBufferAttribute を使用して安全に新しい BufferAttribute を作成し、\n * 元のバッファを変更せずに処理する。\n *\n * @param skinnedMeshes - 処理対象のSkinnedMesh配列\n */\nfunction rotateAllVertexBuffers(skinnedMeshes: SkinnedMesh[]): void {\n /**\n * Y軸180度回転を適用する編集関数\n * 回転行列 [[−1, 0, 0], [0, 1, 0], [0, 0, −1]] を適用\n */\n function rotateVec3Array(array: Float32Array): void {\n const count = array.length / 3\n for (let i = 0; i < count; i++) {\n const baseIdx = i * 3\n array[baseIdx + 0] = -array[baseIdx + 0] // x = -x\n array[baseIdx + 2] = -array[baseIdx + 2] // z = -z\n }\n }\n\n /**\n * BufferAttribute を回転して geometry に設定\n */\n function rotateAndSetAttribute(\n geometry: SkinnedMesh['geometry'],\n attrName: string,\n attr: BufferAttribute | InterleavedBufferAttribute,\n ): void {\n if (attr.itemSize !== 3) return\n\n const rotated = editBufferAttribute<Float32Array>(attr, rotateVec3Array)\n geometry.setAttribute(attrName, rotated)\n }\n\n // 処理済みのgeometryを追跡(共有geometryの重複処理を防ぐ)\n const processedGeometries = new Set<SkinnedMesh['geometry']>()\n\n // 各SkinnedMeshを処理\n for (const mesh of skinnedMeshes) {\n const geometry = mesh.geometry\n\n // 既に処理済みのgeometryはスキップ\n if (processedGeometries.has(geometry)) {\n continue\n }\n processedGeometries.add(geometry)\n\n // position属性\n const posAttr = geometry.getAttribute('position')\n if (posAttr) {\n rotateAndSetAttribute(geometry, 'position', posAttr)\n }\n\n // normal属性\n const normalAttr = geometry.getAttribute('normal')\n if (normalAttr) {\n rotateAndSetAttribute(geometry, 'normal', normalAttr)\n }\n\n // morphTarget position属性\n const morphPositions = geometry.morphAttributes.position\n if (morphPositions && Array.isArray(morphPositions)) {\n for (let i = 0; i < morphPositions.length; i++) {\n const morphAttr = morphPositions[i]\n if (morphAttr.itemSize !== 3) continue\n // 既存の配列を直接編集(GPUキャッシュ問題を回避)\n const array = morphAttr.array as Float32Array\n rotateVec3Array(array)\n morphAttr.needsUpdate = true\n }\n }\n\n // morphTarget normal属性\n const morphNormals = geometry.morphAttributes.normal\n if (morphNormals && Array.isArray(morphNormals)) {\n for (let i = 0; i < morphNormals.length; i++) {\n const morphAttr = morphNormals[i]\n if (morphAttr.itemSize !== 3) continue\n // 既存の配列を直接編集\n const array = morphAttr.array as Float32Array\n rotateVec3Array(array)\n morphAttr.needsUpdate = true\n }\n }\n\n // Three.jsのmorphテクスチャキャッシュを無効化するためdisposeイベントを発火\n // これにより次のレンダリングでmorphデータが再アップロードされる\n geometry.dispatchEvent({ type: 'dispose' })\n }\n}\n\n/**\n * スケルトン内の全ボーンのワールド座標を記録\n */\nexport function recordBoneWorldPositions(\n skeleton: Skeleton,\n): Map<Bone, Vector3> {\n const positions = new Map<Bone, Vector3>()\n\n // ワールド行列を更新\n if (skeleton.bones.length > 0) {\n skeleton.bones[0].updateWorldMatrix(true, true)\n }\n\n for (const bone of skeleton.bones) {\n const worldPos = new Vector3()\n bone.getWorldPosition(worldPos)\n positions.set(bone, worldPos.clone())\n }\n\n return positions\n}\n\n/**\n * ボーン座標をY軸周り180度回転\n */\nexport function rotateBonePositions(\n positions: Map<Bone, Vector3>,\n): Map<Bone, Vector3> {\n const rotated = new Map<Bone, Vector3>()\n const rotationMatrix = new Matrix4().makeRotationY(Math.PI)\n\n for (const [bone, pos] of positions) {\n const newPos = pos.clone().applyMatrix4(rotationMatrix)\n rotated.set(bone, newPos)\n }\n\n return rotated\n}\n\n/**\n * スケルトンのルートボーンを特定\n * 親がBoneでないボーンをルートとして返す\n */\nexport function findRootBone(skeleton: Skeleton): Bone | null {\n for (const bone of skeleton.bones) {\n // 親がBoneでない場合、このボーンがルート\n if (!(bone.parent instanceof Bone)) {\n return bone\n }\n }\n return skeleton.bones[0] || null\n}\n\n/**\n * ルートからツリーを下りながらボーンのローカル変換を再計算\n *\n * VRM1.0仕様では Humanoid Bone のみ rotation が identity である必要がある。\n * 非Humanoid Bone(髪、服、SpringBone制御のボーンなど)は相対的な回転を保持する。\n *\n * @param rootBone - ルートボーン\n * @param rotatedPositions - Y軸180度回転後のワールド座標\n * @param humanoidBones - Humanoid Boneのセット(これらのみidentityにする)\n */\nexport function rebuildBoneTransforms(\n rootBone: Bone,\n rotatedPositions: Map<Bone, Vector3>,\n humanoidBones?: Set<Bone>,\n): void {\n const identityQuat = new Quaternion()\n const rotationMatrix = new Matrix4().makeRotationY(Math.PI)\n const rotationQuat = new Quaternion().setFromRotationMatrix(rotationMatrix)\n\n /**\n * ボーンを処理する再帰関数\n * @param bone - 処理対象のボーン\n * @param parentWorldMatrix - 親のワールド行列\n */\n function processBone(bone: Bone, parentWorldMatrix: Matrix4): void {\n let targetWorldPos = rotatedPositions.get(bone)\n\n // rotatedPositionsに含まれないボーン(SpringBone専用ボーンなど)は\n // 現在のワールド位置を取得してY軸180度回転\n if (!targetWorldPos) {\n bone.updateMatrixWorld(true)\n const currentWorldPos = new Vector3()\n bone.getWorldPosition(currentWorldPos)\n targetWorldPos = currentWorldPos.applyMatrix4(rotationMatrix)\n }\n\n // 親のワールド行列の逆行列を計算\n const parentWorldMatrixInverse = parentWorldMatrix.clone().invert()\n\n // Humanoid Boneかどうかで処理を分岐\n const isHumanoidBone = humanoidBones?.has(bone) ?? true\n\n if (isHumanoidBone) {\n // Humanoid Bone: VRM1.0仕様に従い rotation を identity にする\n bone.quaternion.copy(identityQuat)\n\n // ローカル位置 = ワールド位置を親のローカル座標系に変換\n // 親の rotation が identity なので、単純な差分で計算できる\n const parentWorldPos = new Vector3().setFromMatrixPosition(\n parentWorldMatrix,\n )\n const localPos = targetWorldPos.clone().sub(parentWorldPos)\n bone.position.copy(localPos)\n } else {\n // 非Humanoid Bone: 相対的な回転を保持\n // マイグレーション前の rotation を Y軸180度回転で調整\n // VRM0のローカル座標系はY軸180度回転しているため、\n // rotation も同様に調整する必要がある\n\n // 現在の回転を取得(マイグレーション前のVRM0での回転)\n const originalLocalQuat = bone.quaternion.clone()\n\n // VRM0→VRM1でローカル座標系がY軸180度回転するため、\n // 元の回転を新しい座標系に変換: q' = R * q * R^-1\n // ここで R は Y軸180度回転\n const newLocalQuat = rotationQuat\n .clone()\n .multiply(originalLocalQuat)\n .multiply(rotationQuat.clone().invert())\n bone.quaternion.copy(newLocalQuat)\n\n // ローカル位置を計算\n // ワールド位置から親のワールド行列の逆行列を適用してローカル位置を求める\n const localPos = targetWorldPos\n .clone()\n .applyMatrix4(parentWorldMatrixInverse)\n bone.position.copy(localPos)\n }\n\n // 行列を更新\n bone.updateMatrix()\n bone.updateMatrixWorld(true)\n\n // 子ボーンを再帰処理(更新後のワールド行列を渡す)\n for (const child of bone.children) {\n if (child instanceof Bone) {\n processBone(child, bone.matrixWorld)\n }\n }\n }\n\n // ルートボーンから開始\n // 親のワールド行列を取得(親がない場合は単位行列)\n let parentWorldMatrix = new Matrix4()\n if (rootBone.parent) {\n rootBone.parent.updateMatrixWorld(true)\n parentWorldMatrix = rootBone.parent.matrixWorld.clone()\n }\n\n processBone(rootBone, parentWorldMatrix)\n}\n\n/**\n * InverseBoneMatrix(skeleton.boneInverses)を再計算\n */\nexport function recalculateBoneInverses(skeleton: Skeleton): void {\n // ワールド行列を更新\n skeleton.bones.forEach((bone) => bone.updateMatrixWorld(true))\n\n // calculateInversesを呼び出し\n // これは各bone.matrixWorldの逆行列をboneInversesに設定する\n skeleton.calculateInverses()\n\n // 行列テクスチャを更新(使用している場合)\n skeleton.computeBoneTexture()\n}\n","import type { VRM } from '@pixiv/three-vrm'\nimport { Bone, Matrix4, Vector3 } from 'three'\n\n/**\n * VRM0マイグレーション前にSpringBoneの末端ボーン方向を記録\n * VRM0ではボーンの回転がボーンの向きを表すため、マイグレーションで回転が\n * identityになる前にこの情報を保存する必要がある\n *\n * @param vrm - VRMオブジェクト\n * @returns ボーンごとのローカル方向ベクトル(正規化済み)\n */\nexport function recordSpringBoneDirections(vrm: VRM): Map<Bone, Vector3> {\n const directions = new Map<Bone, Vector3>()\n\n if (!vrm.springBoneManager) return directions\n\n const springBoneManager = vrm.springBoneManager\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const joints = (springBoneManager as any).joints\n if (!joints || joints.size === 0) return directions\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n joints.forEach((joint: any) => {\n const bone = joint.bone as Bone | undefined\n if (!bone) return\n\n // joint.childがなく、bone.childrenにBoneがない場合は末端\n const hasJointChild = joint.child != null\n const hasBoneChild = bone.children.some(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (child: any) => child.type === 'Bone' || child.isBone,\n )\n\n if (!hasJointChild && !hasBoneChild) {\n // bone.positionはこのボーンの親からの相対位置\n // VRM0ではこれがボーンの「向き」を表す\n // マイグレーション後もこの方向を維持するために記録\n const direction = new Vector3().copy(bone.position)\n if (direction.lengthSq() > 0) {\n direction.normalize()\n } else {\n // positionがゼロの場合はY軸方向\n direction.set(0, 1, 0)\n }\n directions.set(bone, direction)\n }\n })\n\n return directions\n}\n\n/**\n * SpringBone末端ジョイントに仮想tailノードを作成\n * VRM1.0仕様ではjointsの最後にtailノードが必要\n * 事前に記録したボーン方向を使用して正しい向きに仮想ノードを追加\n *\n * @param vrm - VRMオブジェクト\n * @param preRecordedDirections - recordSpringBoneDirectionsで記録した方向\n * @returns 作成された仮想tailノードの配列(クリーンアップ用)\n */\nexport function createVirtualTailNodes(\n vrm: VRM,\n preRecordedDirections?: Map<Bone, Vector3>,\n): Bone[] {\n const createdTailNodes: Bone[] = []\n\n if (!vrm.springBoneManager) return createdTailNodes\n\n const springBoneManager = vrm.springBoneManager\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const joints = (springBoneManager as any).joints\n if (!joints || joints.size === 0) return createdTailNodes\n\n // 末端ジョイント(childを持たないジョイント)を見つけて仮想tailを作成\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n joints.forEach((joint: any) => {\n const bone = joint.bone as Bone | undefined\n if (!bone) return\n\n // joint.childがなく、bone.childrenにBoneがない場合は末端\n const hasJointChild = joint.child != null\n\n const hasBoneChild = bone.children.some(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (child: any) => child.type === 'Bone' || child.isBone,\n )\n\n if (!hasJointChild && !hasBoneChild) {\n // 仮想tailノードを作成\n const tailBone = new Bone()\n tailBone.name = `${bone.name}_tail`\n\n // 事前記録された方向を使用(VRM0マイグレーションの場合)\n // なければ現在のbone.positionから計算\n let direction: Vector3\n if (preRecordedDirections?.has(bone)) {\n direction = preRecordedDirections\n .get(bone)!\n .clone()\n .multiplyScalar(0.07)\n } else {\n // three-vrmと同様のロジック: bone.positionを正規化して0.07を掛ける\n direction = new Vector3().copy(bone.position)\n if (direction.lengthSq() > 0) {\n direction.normalize().multiplyScalar(0.07)\n } else {\n // positionがゼロの場合はY軸方向に7cm\n direction.set(0, 0.07, 0)\n }\n }\n tailBone.position.copy(direction)\n\n // 親ボーンに追加\n bone.add(tailBone)\n tailBone.updateMatrixWorld(true)\n\n createdTailNodes.push(tailBone)\n }\n })\n\n return createdTailNodes\n}\n\n/**\n * 作成した仮想tailノードをクリーンアップ\n *\n * @param tailNodes - createVirtualTailNodesで作成されたノードの配列\n */\nexport function cleanupVirtualTailNodes(tailNodes: Bone[]): void {\n for (const tailNode of tailNodes) {\n if (tailNode.parent) {\n tailNode.parent.remove(tailNode)\n }\n }\n}\n\n/**\n * SpringBoneの重力方向(gravityDir)をY軸180度回転\n * VRM0→VRM1マイグレーション時に必要\n *\n * gravityDirはワールド座標系で指定されるため、\n * モデルの向きがY軸180度回転した場合は重力方向も同様に回転する必要がある\n *\n * @param vrm - VRMオブジェクト\n */\nexport function rotateSpringBoneGravityDirections(vrm: VRM): void {\n if (!vrm.springBoneManager) {\n return\n }\n\n const springBoneManager = vrm.springBoneManager\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const joints = (springBoneManager as any).joints\n if (!joints || joints.size === 0) {\n return\n }\n\n const rotationMatrix = new Matrix4().makeRotationY(Math.PI)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n joints.forEach((joint: any) => {\n const settings = joint.settings\n if (!settings || !settings.gravityDir) return\n\n // gravityDirをY軸180度回転(X, Zを反転)\n const gravityDir = settings.gravityDir as Vector3\n gravityDir.applyMatrix4(rotationMatrix)\n })\n}\n\n/**\n * SpringBoneジョイントの状態(_currentTailと_boneAxis)を記録\n * VRM0→VRM1マイグレーション前に呼び出す\n *\n * @param vrm - VRMオブジェクト\n * @returns ジョイントごとの状態(_currentTailワールド座標と_boneAxis方向)\n */\nexport function recordSpringBoneState(\n vrm: VRM,\n): Map<Bone, { currentTail: Vector3; boneAxis: Vector3 }> {\n const states = new Map<Bone, { currentTail: Vector3; boneAxis: Vector3 }>()\n\n if (!vrm.springBoneManager) return states\n\n const springBoneManager = vrm.springBoneManager\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const joints = (springBoneManager as any).joints\n if (!joints || joints.size === 0) return states\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n joints.forEach((joint: any) => {\n const bone = joint.bone as Bone | undefined\n const currentTail = joint._currentTail as Vector3 | undefined\n const boneAxis = joint._boneAxis as Vector3 | undefined\n if (bone && currentTail && boneAxis) {\n states.set(bone, {\n currentTail: currentTail.clone(),\n boneAxis: boneAxis.clone(),\n })\n }\n })\n\n return states\n}\n\n/**\n * @deprecated recordSpringBoneStateを使用してください\n */\nexport function recordSpringBoneCurrentTails(vrm: VRM): Map<Bone, Vector3> {\n const tails = new Map<Bone, Vector3>()\n const states = recordSpringBoneState(vrm)\n states.forEach((state, bone) => {\n tails.set(bone, state.currentTail)\n })\n return tails\n}\n\n/**\n * SpringBoneの状態を復元\n * VRM0→VRM1マイグレーション後、setInitState() + reset()の後に呼び出す\n *\n * マイグレーションでボーンのローカル座標系がY軸180度回転するため、\n * SpringBoneの内部状態も調整が必要。\n *\n * reset()は_initialLocalChildPositionから_boneAxisを再計算するため、\n * この関数はreset()の後に呼び出す必要がある。\n *\n * @param vrm - VRMオブジェクト\n * @param preRecordedState - recordSpringBoneStateで記録した状態\n */\nexport function restoreSpringBoneState(\n vrm: VRM,\n preRecordedState: Map<Bone, { currentTail: Vector3; boneAxis: Vector3 }>,\n): void {\n if (!vrm.springBoneManager) {\n return\n }\n\n const springBoneManager = vrm.springBoneManager\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const joints = (springBoneManager as any).joints\n if (!joints || joints.size === 0) {\n return\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n joints.forEach((joint: any) => {\n const bone = joint.bone as Bone | undefined\n if (!bone || !preRecordedState.has(bone)) return\n\n const state = preRecordedState.get(bone)!\n\n // _boneAxisを元の値に復元\n const boneAxis = joint._boneAxis as Vector3 | undefined\n if (boneAxis) {\n boneAxis.copy(state.boneAxis)\n }\n\n // _currentTailと_prevTailを調整\n // マイグレーション後、bone.matrixWorldの位置成分がY軸180度回転しているため、\n // _currentTailもボーンの新しい位置からの相対位置として再計算する必要がある\n const currentTail = joint._currentTail as Vector3 | undefined\n const prevTail = joint._prevTail as Vector3 | undefined\n\n if (currentTail) {\n // reset()で計算された_currentTailを使用(bone.localToWorld(_initialLocalChildPosition))\n // これはマイグレーション後のボーン位置に対して正しい相対位置になっている\n // _boneAxisだけを復元すれば、stiffnessによる復元力の方向は正しくなる\n\n // 注意: state.currentTailはマイグレーション前のワールド座標\n // マイグレーション後はボーンのワールド位置が変わっているため、\n // そのまま復元すると不整合が起きる\n // reset()で計算された値をそのまま使用する\n\n // _prevTailは_currentTailと同じに設定(初期状態では慣性がない)\n if (prevTail) {\n prevTail.copy(currentTail)\n }\n }\n })\n}\n\n/**\n * SpringBoneの内部軸(_boneAxis)をY軸180度回転\n * VRM0→VRM1マイグレーション後にsetInitState()を呼んだ後に必要\n *\n * @deprecated restoreSpringBoneStateを使用してください\n *\n * @param vrm - VRMオブジェクト\n * @param preRecordedTails - recordSpringBoneCurrentTailsで記録したワールド座標(オプション)\n */\nexport function rotateSpringBoneBoneAxis(\n vrm: VRM,\n preRecordedTails?: Map<Bone, Vector3>,\n): void {\n if (!vrm.springBoneManager) {\n return\n }\n\n const springBoneManager = vrm.springBoneManager\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const joints = (springBoneManager as any).joints\n if (!joints || joints.size === 0) {\n return\n }\n\n const rotationMatrix = new Matrix4().makeRotationY(Math.PI)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n joints.forEach((joint: any) => {\n const bone = joint.bone as Bone | undefined\n if (!bone) return\n\n // _boneAxisをY軸180度回転(X, Zを反転して元に戻す)\n // これによりworldSpaceBoneAxisがマイグレーション前と同じ方向を維持する\n const boneAxis = joint._boneAxis as Vector3 | undefined\n if (boneAxis) {\n boneAxis.applyMatrix4(rotationMatrix)\n }\n\n // _initialLocalChildPositionを再計算\n // 記録されたワールド座標(_currentTail)から、新しいbone.matrixWorldに対応した\n // ローカル座標を逆算する\n const initialLocalChildPosition = joint._initialLocalChildPosition as\n | Vector3\n | undefined\n if (initialLocalChildPosition && preRecordedTails?.has(bone)) {\n const targetWorldPos = preRecordedTails.get(bone)!\n // ワールド座標からローカル座標に逆変換\n // bone.worldToLocal()は引数を変更するのでcloneを渡す\n const newLocalPos = bone.worldToLocal(targetWorldPos.clone())\n initialLocalChildPosition.copy(newLocalPos)\n }\n })\n}\n\n/**\n * SpringBoneコライダーのオフセットをY軸180度回転\n * VRM0→VRM1マイグレーション時に必要\n *\n * コライダーはHumanoid Bone(Head等)にアタッチされており、\n * offset/tailはローカル座標系で定義されている。\n * マイグレーション後、Humanoid Boneの回転はidentityになるが、\n * ローカル座標系自体がY軸180度回転しているため、\n * コライダーのオフセットも同様に回転する必要がある。\n *\n * @param vrm - VRMオブジェクト\n */\nexport function rotateSpringBoneColliderOffsets(vrm: VRM): void {\n if (!vrm.springBoneManager) {\n return\n }\n\n const colliders = vrm.springBoneManager.colliders\n if (!colliders || colliders.length === 0) {\n return\n }\n\n const rotationMatrix = new Matrix4().makeRotationY(Math.PI)\n\n for (const collider of colliders) {\n const shape = collider.shape\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const shapeAny = shape as any\n\n // sphere型とcapsule型の両方でoffsetプロパティがある\n if (shapeAny.offset instanceof Vector3) {\n shapeAny.offset.applyMatrix4(rotationMatrix)\n }\n\n // capsule型の場合はtailプロパティもある\n if (shapeAny.tail instanceof Vector3) {\n shapeAny.tail.applyMatrix4(rotationMatrix)\n }\n }\n}\n\n/**\n * VRM0→VRM1マイグレーション後にSpringBone関連の調整を一括で実行\n *\n * 以下の処理を順番に実行:\n * 1. 末端ジョイントに仮想tailノードを作成\n * 2. 重力方向(gravityDir)をY軸180度回転\n * 3. コライダーオフセットをY軸180度回転\n * 4. SpringBoneの初期状態を再設定\n *\n * @param vrm - VRMオブジェクト\n * @returns 作成された仮想tailノードの配列(クリーンアップ用)\n */\nexport function migrateSpringBone(vrm: VRM): Bone[] {\n // 末端ジョイントに仮想tailノードを作成\n const tailNodes = createVirtualTailNodes(vrm)\n\n // 重力方向をY軸180度回転\n rotateSpringBoneGravityDirections(vrm)\n\n // コライダーオフセットをY軸180度回転\n rotateSpringBoneColliderOffsets(vrm)\n\n // SpringBoneの初期状態を再設定\n vrm.springBoneManager?.setInitState()\n vrm.springBoneManager?.reset()\n\n return tailNodes\n}\n","import { MToonMaterial, VRM } from '@pixiv/three-vrm'\nimport { ok, ResultAsync, safeTry } from 'neverthrow'\nimport { Bone, BufferAttribute, Mesh } from 'three'\nimport { generateAtlasImagesFromPatterns } from './process/gen-atlas'\nimport { buildPatternMaterialMappings, pack } from './process/packing'\nimport { applyPlacementsToGeometries } from './process/set-uv'\nimport { simplifyMeshes, SimplifyStatistics } from './process/simplify'\nimport { OffsetScale, OptimizationError, OptimizeModelOptions } from './types'\nimport {\n assignAtlasTexturesToMaterial,\n CombinedMeshResult,\n combineMToonMaterials as combineMeshAndMaterial,\n getMToonMaterialInfoFromObject3D,\n} from './util/material'\nimport { deleteMesh } from './util/mesh/deleter'\nimport { migrateSkeletonVRM0ToVRM1 } from './util/skeleton'\nimport { migrateSpringBone } from './util/springbone'\n\n/**\n * 受け取ったThree.jsオブジェクトのツリーのメッシュ及びそのマテリアルを走査し、\n * Three.jsの複数MToonNodeMaterialをチャンネルごとにテクスチャパッキング\n * アトラス化したテクスチャを各マテリアルに設定する\n * 対応するメッシュのUVをパッキング結果に基づき修正する\n * 最後にマテリアルを統合してドローコール数を削減する\n *\n * @param vrm - 最適化対象のVRMオブジェクト\n * @param options - 最適化オプション\n * @returns 最適化結果(統合メッシュ情報を含む)\n */\nexport function optimizeModel(\n vrm: VRM,\n options: OptimizeModelOptions = {},\n): ResultAsync<CombinedMeshResult, OptimizationError> {\n return safeTry(async function* () {\n const rootNode = vrm.scene\n\n // SpringBoneを初期姿勢にリセット(マイグレーション前に物理演算の影響を排除)\n vrm.springBoneManager?.reset()\n\n // モデルのマテリアル集計(アウトライン情報を含む)\n const materialInfos = yield* getMToonMaterialInfoFromObject3D(rootNode)\n const materials = materialInfos.map((info) => info.material)\n\n // 後方互換性のためのMap生成\n const materialMeshMap = new Map<MToonMaterial, Mesh[]>()\n for (const info of materialInfos) {\n materialMeshMap.set(info.material, info.meshes)\n }\n\n // マテリアルで使われてるテクスチャの組のパターンを集計\n const patternMappings = buildPatternMaterialMappings(materials)\n\n // パッキングレイアウトを構築\n const packLayouts = yield* await pack(patternMappings)\n\n // パターンごとのアトラス画像を生成\n const atlasMap = yield* generateAtlasImagesFromPatterns(\n materials,\n patternMappings,\n packLayouts.packed,\n options.atlas,\n )\n\n // アトラス画像をマテリアルにそれぞれアサインする\n const materialPlacementMap = new Map<MToonMaterial, OffsetScale>()\n patternMappings.forEach((mapping, index) => {\n const placement = packLayouts.packed[index]\n for (const materialIndex of mapping.materialIndices) {\n const material = materials[materialIndex]\n assignAtlasTexturesToMaterial(material, atlasMap)\n materialPlacementMap.set(material, placement)\n }\n })\n\n // アトラス画像をマテリアルにそれぞれアサインする\n // アトラス画像の配置に合わせてUVを移動する\n yield* applyPlacementsToGeometries(rootNode, materialPlacementMap)\n\n // 顔メッシュ(表情で使われているメッシュ)を特定\n // 簡略化とメッシュ統合から除外するメッシュのSet\n const excludedMeshes = new Set<Mesh>()\n if (vrm.expressionManager) {\n for (const expression of vrm.expressionManager.expressions) {\n for (const bind of expression.binds) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const bindAny = bind as any\n\n // MorphTargetBind\n if (bindAny.primitives) {\n for (const mesh of bindAny.primitives) {\n if (mesh && mesh.isMesh) {\n excludedMeshes.add(mesh)\n }\n }\n }\n\n // MaterialColorBind / TextureTransformBind\n if (bindAny.material) {\n const meshes = materialMeshMap.get(bindAny.material)\n if (meshes) {\n meshes.forEach((mesh) => excludedMeshes.add(mesh))\n }\n }\n }\n }\n }\n\n // メッシュ簡略化(オプションが設定されている場合)\n // UVリマッピング後、メッシュ統合前に実行\n let simplifyStats: SimplifyStatistics | undefined\n if (options.simplify) {\n simplifyStats = yield* await simplifyMeshes(\n rootNode,\n excludedMeshes,\n options.simplify,\n )\n }\n\n // 複数のMesh及びMToonMaterialを統合してドローコール数を削減\n // レンダーモード(opaque/alphaTest/transparent)ごとに別メッシュとして結合\n const combineResult = yield* combineMeshAndMaterial(\n materialInfos,\n {},\n excludedMeshes,\n )\n\n // excludedMeshesにもMToonAtlasMaterialを適用\n // これにより、エクスポート→インポート後も正しくレンダリングされる\n // 最初のグループからスロット属性名を取得\n const firstGroup = combineResult.groups.values().next().value\n const slotAttributeName =\n firstGroup?.material.slotAttribute?.name || 'mtoonMaterialSlot'\n\n for (const mesh of excludedMeshes) {\n // メッシュのマテリアルを取得\n const originalMaterial = Array.isArray(mesh.material)\n ? mesh.material[0]\n : mesh.material\n\n if (!(originalMaterial instanceof MToonMaterial)) continue\n\n // スロット情報を取得\n const slotInfo = combineResult.materialSlotIndex.get(originalMaterial)\n if (!slotInfo) continue\n\n // 対応するレンダーモードのグループを取得\n const group = combineResult.groups.get(slotInfo.renderMode)\n if (!group) continue\n\n // ジオメトリにスロット属性を追加\n const geometry = mesh.geometry\n const vertexCount = geometry.getAttribute('position').count\n const slotArray = new Float32Array(vertexCount).fill(slotInfo.slotIndex)\n geometry.setAttribute(\n slotAttributeName,\n new BufferAttribute(slotArray, 1),\n )\n\n // MToonAtlasMaterialを適用(同じレンダーモードのマテリアルを共有)\n mesh.material = group.material\n }\n\n // 元のrootNodeから既存のメッシュを削除\n const meshesToRemove: Mesh[] = []\n for (const meshes of materialMeshMap.values()) {\n for (const mesh of meshes) {\n if (!excludedMeshes.has(mesh)) {\n meshesToRemove.push(mesh)\n }\n }\n }\n\n // 最初のメッシュの親を取得(結合後のメッシュを同じ親に追加するため)\n const firstMeshParent = meshesToRemove[0]?.parent || rootNode\n\n meshesToRemove.forEach((mesh) => mesh.parent?.remove(mesh))\n\n // バッファを削除\n for (const mesh of meshesToRemove) {\n deleteMesh(mesh)\n }\n\n // 各レンダーモードのメッシュをシーンに追加\n // アウトラインメッシュを先に追加することで、glTF/VRMエクスポート後も\n // 正しい描画順序を維持(ノードの順序が描画順序に影響するため)\n for (const group of combineResult.groups.values()) {\n // アウトラインを先に追加(先に描画される = 後ろに表示される)\n if (group.outlineMesh) {\n firstMeshParent.add(group.outlineMesh)\n }\n // excludedMeshes専用グループの場合はmeshがnull\n if (group.mesh) {\n firstMeshParent.add(group.mesh)\n }\n }\n\n // VRM0.x -> VRM1.0 スケルトンマイグレーション(メッシュ統合後に実行)\n if (options.migrateVRM0ToVRM1) {\n // SpringBoneManagerを一時的に退避\n // マイグレーション中に外部からvrm.update()が呼ばれても\n // SpringBoneが動かないようにする\n const springBoneManager = vrm.springBoneManager\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(vrm as any).springBoneManager = null\n\n // SpringBoneを初期姿勢にリセット(物理演算による変形を排除)\n // マイグレーションはボーンのワールド座標を記録するため、\n // 物理演算で変形した状態だと正しい座標が記録されない\n springBoneManager?.reset()\n\n // Humanoid Boneのセットを構築\n // VRM1.0仕様ではHumanoid Boneのみ回転がidentityである必要がある\n // 非Humanoid Bone(髪、服、SpringBone制御のボーンなど)は回転を保持\n const humanoidBones = new Set<Bone>()\n if (vrm.humanoid) {\n Object.values(vrm.humanoid.humanBones).forEach((humanBone) => {\n const node = humanBone.node\n if (node instanceof Bone) {\n humanoidBones.add(node)\n }\n })\n }\n\n yield* migrateSkeletonVRM0ToVRM1(rootNode, { humanoidBones })\n\n // SpringBoneManagerを復元(migrateSpringBoneがspringBoneManagerを使うため)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(vrm as any).springBoneManager = springBoneManager\n\n // SpringBone関連の調整を一括で実行\n // - 末端ジョイントに仮想tailノードを作成\n // - 重力方向(gravityDir)をY軸180度回転\n // - コライダーオフセットをY軸180度回転\n // - SpringBoneの初期状態を再設定\n migrateSpringBone(vrm)\n }\n\n // 簡略化統計を結果に追加\n if (simplifyStats) {\n combineResult.statistics.simplify = simplifyStats\n }\n\n return ok(combineResult)\n })\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { VRM } from '@pixiv/three-vrm'\nimport { Bone, Object3D, Vector3 } from 'three'\n\nexport class VRMExporterPlugin {\n public readonly name = 'VRMC_vrm'\n private writer: any\n private vrm: VRM | null = null\n // 動的に作成されたtailノードを追跡(エクスポート後にクリーンアップするため)\n private createdTailNodes: Bone[] = []\n\n constructor(writer: any) {\n this.writer = writer\n }\n\n public setVRM(vrm: VRM) {\n this.vrm = vrm\n }\n\n public beforeParse(input: Object3D | Object3D[]) {\n const root = Array.isArray(input) ? input[0] : input\n if (!root) return\n\n // Find VRM instance in userData\n // This assumes the input object or its children have userData.vrm set\n // which is common when loading via VRMLoaderPlugin\n root.traverse((obj: any) => {\n if (obj.userData && obj.userData.vrm && !this.vrm) {\n this.vrm = obj.userData.vrm as VRM\n }\n })\n\n // SpringBone末端ジョイントに仮想tailノードを作成\n // VRM1.0仕様ではjointsの最後にtailノードが必要だが、\n // VRM0.xモデルや一部のVRM1.0モデルでは末端ボーンに子がない\n this.createVirtualTailNodes()\n }\n\n /**\n * SpringBone末端ジョイントに仮想tailノードを作成\n * three-vrmと同様に、ボーン方向に7cmのオフセットを持つ仮想ノードを追加\n */\n private createVirtualTailNodes(): void {\n if (!this.vrm?.springBoneManager) return\n\n const springBoneManager = this.vrm.springBoneManager\n const joints = springBoneManager.joints\n if (!joints || joints.size === 0) return\n\n // ジョイントをボーンでマッピング\n const jointsByBone = new Map<any, any>()\n joints.forEach((joint: any) => {\n jointsByBone.set(joint.bone, joint)\n })\n\n // 末端ジョイント(childを持たないジョイント)を見つける\n joints.forEach((joint: any) => {\n const bone = joint.bone\n if (!bone) return\n\n // joint.childがなく、bone.childrenにBoneがない場合は末端\n const hasJointChild = joint.child != null\n const hasBoneChild = bone.children.some(\n (child: any) => child.type === 'Bone' || child.isBone,\n )\n\n if (!hasJointChild && !hasBoneChild) {\n // 仮想tailノードを作成\n const tailBone = new Bone()\n tailBone.name = `${bone.name}_tail`\n\n // three-vrmと同様のロジック: ボーン方向に7cmオフセット\n // bone.positionを正規化して0.07を掛ける\n const direction = new Vector3().copy(bone.position)\n if (direction.lengthSq() > 0) {\n direction.normalize().multiplyScalar(0.07)\n } else {\n // positionがゼロの場合はY軸方向に7cm\n direction.set(0, 0.07, 0)\n }\n tailBone.position.copy(direction)\n\n // 親ボーンに追加\n bone.add(tailBone)\n tailBone.updateMatrixWorld(true)\n\n this.createdTailNodes.push(tailBone)\n }\n })\n }\n\n /**\n * エクスポート後に作成した仮想tailノードをクリーンアップ\n */\n public cleanupTailNodes(): void {\n for (const tailNode of this.createdTailNodes) {\n if (tailNode.parent) {\n tailNode.parent.remove(tailNode)\n }\n }\n this.createdTailNodes = []\n }\n\n public afterParse(_input: any) {\n if (!this.vrm) {\n return\n }\n\n // writer.jsonに直接アクセスして拡張を追加\n // afterParseの引数はinputオブジェクトのみで、JSONは含まれない\n const json = this.writer.json\n const vrm = this.vrm\n\n json.extensions = json.extensions || {}\n json.extensions.VRMC_vrm = {\n specVersion: '1.0',\n meta: this.exportMeta(vrm),\n humanoid: this.exportHumanoid(vrm),\n expressions: this.exportExpressions(vrm),\n lookAt: this.exportLookAt(vrm),\n firstPerson: this.exportFirstPerson(vrm),\n }\n\n json.extensionsUsed = json.extensionsUsed || []\n if (!json.extensionsUsed.includes('VRMC_vrm')) {\n json.extensionsUsed.push('VRMC_vrm')\n }\n\n // SpringBone拡張をエクスポート\n const springBoneExtension = this.exportSpringBone(vrm)\n if (springBoneExtension) {\n json.extensions.VRMC_springBone = springBoneExtension\n if (!json.extensionsUsed.includes('VRMC_springBone')) {\n json.extensionsUsed.push('VRMC_springBone')\n }\n }\n }\n\n private exportMeta(vrm: VRM) {\n if (!vrm.meta) return undefined\n\n const meta = vrm.meta as any // Cast to any to handle both VRM 0.0 and 1.0 meta types\n\n // Map VRM 0.0 meta to VRM 1.0 if necessary, or just use what's available\n // VRM 0.0 uses 'title', VRM 1.0 uses 'name'\n\n // VRM 0.0のライセンス名をVRM 1.0のライセンスURLに変換\n let licenseUrl = meta.licenseUrl\n if (!licenseUrl && meta.licenseName) {\n // VRM 0.0のライセンス名からVRM 1.0のURLへマッピング\n const licenseMapping: Record<string, string> = {\n Redistribution_Prohibited: 'https://vrm.dev/licenses/1.0/',\n CC0: 'https://creativecommons.org/publicdomain/zero/1.0/',\n CC_BY: 'https://creativecommons.org/licenses/by/4.0/',\n CC_BY_NC: 'https://creativecommons.org/licenses/by-nc/4.0/',\n CC_BY_SA: 'https://creativecommons.org/licenses/by-sa/4.0/',\n CC_BY_NC_SA: 'https://creativecommons.org/licenses/by-nc-sa/4.0/',\n CC_BY_ND: 'https://creativecommons.org/licenses/by-nd/4.0/',\n CC_BY_NC_ND: 'https://creativecommons.org/licenses/by-nc-nd/4.0/',\n Other: 'https://vrm.dev/licenses/1.0/',\n }\n licenseUrl =\n licenseMapping[meta.licenseName] ?? 'https://vrm.dev/licenses/1.0/'\n }\n\n // licenseUrlが未定義の場合はデフォルトを設定\n if (!licenseUrl) {\n licenseUrl = 'https://vrm.dev/licenses/1.0/'\n }\n\n return {\n name: meta.name ?? meta.title,\n version: meta.version,\n authors: meta.authors ?? (meta.author ? [meta.author] : undefined),\n copyrightInformation: meta.copyrightInformation,\n contactInformation: meta.contactInformation,\n references:\n meta.references ?? (meta.reference ? [meta.reference] : undefined),\n thirdPartyLicenses: meta.thirdPartyLicenses,\n thumbnailImage: meta.thumbnailImage\n ? this.writer.processTexture(meta.thumbnailImage)\n : undefined,\n licenseUrl,\n avatarPermission: meta.avatarPermission ?? 'onlyAuthor',\n allowExcessivelyViolentUsage: meta.allowExcessivelyViolentUsage ?? false,\n allowExcessivelySexualUsage: meta.allowExcessivelySexualUsage ?? false,\n commercialUsage: meta.commercialUsage ?? 'personalNonProfit',\n allowPoliticalOrReligiousUsage:\n meta.allowPoliticalOrReligiousUsage ?? false,\n allowAntisocialOrHateUsage: meta.allowAntisocialOrHateUsage ?? false,\n creditNotation: meta.creditNotation ?? 'required',\n allowRedistribution: meta.allowRedistribution ?? false,\n modification: meta.modification ?? 'prohibited',\n }\n }\n\n private exportHumanoid(vrm: VRM) {\n if (!vrm.humanoid) return undefined\n\n const humanBones: any = {}\n\n // Iterate over all possible human bone names\n Object.entries(vrm.humanoid.humanBones).forEach(([name, bone]) => {\n if (bone && bone.node) {\n // Find the node index in the exported GLTF\n // The writer should have a map of Object3D to node index\n // However, standard GLTFExporter doesn't expose this easily in public API\n // We rely on the fact that writer.processNode returns the index,\n // but we are in afterParse, so nodes are already processed.\n // We need to find the node index.\n // A common workaround is to use the cache or map if available,\n // or re-traverse. But GLTFExporter usually attaches the index to userData during parse?\n // No, it doesn't.\n\n // We can use writer.nodeMap if it exists (it's a Map<Object3D, number>)\n // In Three.js GLTFExporter, it uses a Map called `nodeMap`.\n const nodeIndex = this.writer.nodeMap.get(bone.node)\n if (nodeIndex !== undefined) {\n humanBones[name] = { node: nodeIndex }\n }\n }\n })\n\n return {\n humanBones,\n }\n }\n\n private exportExpressions(vrm: VRM) {\n if (!vrm.expressionManager) return undefined\n\n // VRM 1.0 の preset 表情名リスト\n const presetNames = new Set([\n 'happy',\n 'angry',\n 'sad',\n 'relaxed',\n 'surprised',\n 'aa',\n 'ih',\n 'ou',\n 'ee',\n 'oh',\n 'blink',\n 'blinkLeft',\n 'blinkRight',\n 'lookUp',\n 'lookDown',\n 'lookLeft',\n 'lookRight',\n 'neutral',\n ])\n\n const preset: any = {}\n const custom: any = {}\n\n if (vrm.expressionManager.expressions) {\n vrm.expressionManager.expressions.forEach((expression) => {\n const expr = expression as any // Cast to access binds\n const exprDef: any = {}\n\n // isBinary, overrideBlink などはデフォルト値(false/none)でなければ出力\n if (expr.isBinary) exprDef.isBinary = expr.isBinary\n if (expr.overrideBlink && expr.overrideBlink !== 'none')\n exprDef.overrideBlink = expr.overrideBlink\n if (expr.overrideLookAt && expr.overrideLookAt !== 'none')\n exprDef.overrideLookAt = expr.overrideLookAt\n if (expr.overrideMouth && expr.overrideMouth !== 'none')\n exprDef.overrideMouth = expr.overrideMouth\n\n // three-vrm では _binds に VRMExpressionMorphTargetBind が格納されている\n const binds = expr._binds || expr.binds || []\n const morphTargetBinds = binds.filter(\n (b: any) => b.type === 'morphTarget' || b.primitives,\n )\n if (morphTargetBinds.length > 0) {\n // 各 bind の primitives すべてに対してエントリを作成\n const allBinds: any[] = []\n morphTargetBinds.forEach((bind: any) => {\n const primitives = bind.primitives || []\n primitives.forEach((mesh: any) => {\n const nodeIndex = this.writer.nodeMap.get(mesh)\n if (nodeIndex !== undefined) {\n allBinds.push({\n node: nodeIndex,\n index: bind.index,\n weight: bind.weight,\n })\n }\n })\n })\n\n if (allBinds.length > 0) {\n exprDef.morphTargetBinds = allBinds\n }\n }\n\n if (expr.materialColorBinds && expr.materialColorBinds.length > 0) {\n exprDef.materialColorBinds = expr.materialColorBinds.map(\n (bind: any) => {\n const materialIndex = this.writer.processMaterial(bind.material)\n return {\n material: materialIndex,\n type: bind.type,\n targetValue: bind.targetValue.toArray(),\n }\n },\n )\n }\n\n if (\n expr.textureTransformBinds &&\n expr.textureTransformBinds.length > 0\n ) {\n exprDef.textureTransformBinds = expr.textureTransformBinds.map(\n (bind: any) => {\n const materialIndex = this.writer.processMaterial(bind.material)\n return {\n material: materialIndex,\n scale: bind.scale.toArray(),\n offset: bind.offset.toArray(),\n }\n },\n )\n }\n\n // preset か custom かを判定して振り分け\n const name = expr.expressionName\n if (presetNames.has(name)) {\n preset[name] = exprDef\n } else {\n custom[name] = exprDef\n }\n })\n }\n\n const result: any = { preset }\n if (Object.keys(custom).length > 0) {\n result.custom = custom\n }\n return result\n }\n\n private exportLookAt(vrm: VRM) {\n if (!vrm.lookAt) return undefined\n\n const lookAt = vrm.lookAt as any\n\n // rangeMapが存在しない場合はデフォルト値を使用\n const defaultRangeMap = { inputMaxValue: 90, outputScale: 10 }\n\n return {\n offsetFromHeadBone: lookAt.offsetFromHeadBone?.toArray?.() ?? [0, 0, 0],\n type: lookAt.applier?.type ?? 'bone', // 'bone' or 'expression'\n rangeMapHorizontalInner: lookAt.rangeMapHorizontalInner\n ? {\n inputMaxValue: lookAt.rangeMapHorizontalInner.inputMaxValue,\n outputScale: lookAt.rangeMapHorizontalInner.outputScale,\n }\n : defaultRangeMap,\n rangeMapHorizontalOuter: lookAt.rangeMapHorizontalOuter\n ? {\n inputMaxValue: lookAt.rangeMapHorizontalOuter.inputMaxValue,\n outputScale: lookAt.rangeMapHorizontalOuter.outputScale,\n }\n : defaultRangeMap,\n rangeMapVerticalDown: lookAt.rangeMapVerticalDown\n ? {\n inputMaxValue: lookAt.rangeMapVerticalDown.inputMaxValue,\n outputScale: lookAt.rangeMapVerticalDown.outputScale,\n }\n : defaultRangeMap,\n rangeMapVerticalUp: lookAt.rangeMapVerticalUp\n ? {\n inputMaxValue: lookAt.rangeMapVerticalUp.inputMaxValue,\n outputScale: lookAt.rangeMapVerticalUp.outputScale,\n }\n : defaultRangeMap,\n }\n }\n\n private exportFirstPerson(vrm: VRM) {\n if (!vrm.firstPerson) return undefined\n\n const meshAnnotations: any[] = []\n if (vrm.firstPerson.meshAnnotations) {\n vrm.firstPerson.meshAnnotations.forEach((annotation) => {\n const ann = annotation as any\n // In three-vrm, annotation might hold 'mesh' (Object3D) instead of 'node' index\n // If it holds 'mesh', we need to find its node index.\n // If it holds 'node' (from raw GLTF), it might be an index or object.\n // Usually in loaded VRM, it holds the Mesh object.\n const mesh = ann.mesh || ann.node\n const nodeIndex = this.writer.nodeMap.get(mesh)\n if (nodeIndex !== undefined) {\n meshAnnotations.push({\n node: nodeIndex,\n type: ann.type,\n })\n }\n })\n }\n\n return {\n meshAnnotations,\n }\n }\n\n /**\n * VRMC_springBone 拡張をエクスポート\n * three-vrm の VRMSpringBoneManager から SpringBone データを抽出\n */\n private exportSpringBone(vrm: VRM) {\n const springBoneManager = vrm.springBoneManager\n if (!springBoneManager) return undefined\n\n const joints = springBoneManager.joints\n if (!joints || joints.size === 0) return undefined\n\n // コライダーをインデックス化\n const colliders = springBoneManager.colliders\n const colliderIndexMap = new Map<any, number>()\n const colliderDefs: any[] = []\n\n colliders.forEach((collider: any) => {\n const nodeIndex = this.writer.nodeMap.get(collider)\n if (nodeIndex === undefined) return\n\n const shape = collider.shape\n let shapeDef: any\n\n if (shape.type === 'sphere') {\n shapeDef = {\n sphere: {\n offset: shape.offset\n ? [shape.offset.x, shape.offset.y, shape.offset.z]\n : [0, 0, 0],\n radius: shape.radius ?? 0,\n },\n }\n } else if (shape.type === 'capsule') {\n shapeDef = {\n capsule: {\n offset: shape.offset\n ? [shape.offset.x, shape.offset.y, shape.offset.z]\n : [0, 0, 0],\n radius: shape.radius ?? 0,\n tail: shape.tail\n ? [shape.tail.x, shape.tail.y, shape.tail.z]\n : [0, 0, 0],\n },\n }\n } else {\n // plane などその他のシェイプはスキップ\n return\n }\n\n const colliderIndex = colliderDefs.length\n colliderIndexMap.set(collider, colliderIndex)\n colliderDefs.push({\n node: nodeIndex,\n shape: shapeDef,\n })\n })\n\n // コライダーグループをインデックス化\n const colliderGroups = springBoneManager.colliderGroups\n const colliderGroupIndexMap = new Map<any, number>()\n const colliderGroupDefs: any[] = []\n\n colliderGroups.forEach((group: any) => {\n const colliderIndices: number[] = []\n group.colliders.forEach((collider: any) => {\n const index = colliderIndexMap.get(collider)\n if (index !== undefined) {\n colliderIndices.push(index)\n }\n })\n\n if (colliderIndices.length > 0) {\n const groupIndex = colliderGroupDefs.length\n colliderGroupIndexMap.set(group, groupIndex)\n colliderGroupDefs.push({\n name: group.name,\n colliders: colliderIndices,\n })\n }\n })\n\n // ジョイントをスプリングにグループ化\n // three-vrm では各ジョイントが独立しているが、\n // VRMC_springBone 仕様ではジョイントチェーンとして表現する\n // ボーンの親子関係からチェーンを再構築する\n const springDefs: any[] = []\n const processedJoints = new Set<any>()\n\n // ジョイントをボーンノードでグループ化\n const jointsByBone = new Map<any, any>()\n joints.forEach((joint: any) => {\n jointsByBone.set(joint.bone, joint)\n })\n\n // ルートジョイント(親がジョイントでないもの)を見つけてチェーンを構築\n joints.forEach((joint: any) => {\n if (processedJoints.has(joint)) return\n\n // このジョイントがチェーンのルートかどうかを確認\n const parentBone = joint.bone.parent\n if (parentBone && jointsByBone.has(parentBone)) {\n // 親もジョイントなのでルートではない\n return\n }\n\n // チェーンを構築\n const chainJoints: any[] = []\n let currentJoint = joint\n\n while (currentJoint && !processedJoints.has(currentJoint)) {\n processedJoints.add(currentJoint)\n chainJoints.push(currentJoint)\n\n // 子ボーンを持つジョイントを探す\n const childBone = currentJoint.child\n currentJoint = childBone ? jointsByBone.get(childBone) : null\n }\n\n if (chainJoints.length === 0) return\n\n // ジョイント定義を作成\n const jointDefs: any[] = []\n\n for (let i = 0; i < chainJoints.length; i++) {\n const j = chainJoints[i]\n const nodeIndex = this.writer.nodeMap.get(j.bone)\n if (nodeIndex === undefined) continue\n\n jointDefs.push({\n node: nodeIndex,\n hitRadius: j.settings.hitRadius,\n stiffness: j.settings.stiffness,\n gravityPower: j.settings.gravityPower,\n gravityDir: j.settings.gravityDir\n ? [\n j.settings.gravityDir.x,\n j.settings.gravityDir.y,\n j.settings.gravityDir.z,\n ]\n : [0, -1, 0],\n dragForce: j.settings.dragForce,\n })\n }\n\n // 末端ノード(tail)を追加\n // VRM1.0仕様: SpringBoneチェーンの最後にはtailノードが必要\n // beforeParseで仮想tailノードを作成済みなので、bone.childrenから取得できる\n const lastJoint = chainJoints[chainJoints.length - 1]\n let tailNode = lastJoint?.child\n\n // child がない場合、bone.children から子ボーンを探す\n // (beforeParseで作成した仮想tailノードを含む)\n if (!tailNode && lastJoint?.bone) {\n const boneChildren = lastJoint.bone.children.filter(\n (child: any) => child.type === 'Bone' || child.isBone,\n )\n if (boneChildren.length > 0) {\n tailNode = boneChildren[0]\n }\n }\n\n if (tailNode) {\n const tailNodeIndex = this.writer.nodeMap.get(tailNode)\n if (tailNodeIndex !== undefined) {\n // tailノードをjointsに追加(nodeのみ、物理パラメータなし)\n jointDefs.push({\n node: tailNodeIndex,\n })\n }\n }\n\n if (jointDefs.length === 0) return\n\n // コライダーグループのインデックスを収集\n const colliderGroupIndices: number[] = []\n const firstJoint = chainJoints[0]\n if (firstJoint.colliderGroups) {\n firstJoint.colliderGroups.forEach((group: any) => {\n const index = colliderGroupIndexMap.get(group)\n if (index !== undefined && !colliderGroupIndices.includes(index)) {\n colliderGroupIndices.push(index)\n }\n })\n }\n\n // センターノードのインデックス\n let centerNodeIndex: number | undefined\n if (firstJoint.center) {\n centerNodeIndex = this.writer.nodeMap.get(firstJoint.center)\n }\n\n const springDef: any = {\n joints: jointDefs,\n }\n\n if (centerNodeIndex !== undefined) {\n springDef.center = centerNodeIndex\n }\n\n if (colliderGroupIndices.length > 0) {\n springDef.colliderGroups = colliderGroupIndices\n }\n\n springDefs.push(springDef)\n })\n\n // 何もエクスポートするものがなければ undefined を返す\n if (springDefs.length === 0 && colliderDefs.length === 0) {\n return undefined\n }\n\n const result: any = {\n specVersion: '1.0',\n }\n\n if (colliderDefs.length > 0) {\n result.colliders = colliderDefs\n }\n\n if (colliderGroupDefs.length > 0) {\n result.colliderGroups = colliderGroupDefs\n }\n\n if (springDefs.length > 0) {\n result.springs = springDefs\n }\n\n return result\n }\n}\n","/**\n * VRM エクスポート機能\n * VRM を Uint8Array (バイナリ) としてエクスポートする\n */\nimport type { VRM } from '@pixiv/three-vrm'\nimport { MToonAtlasExporterPlugin } from '@webxr-jp/mtoon-atlas'\nimport { initBasisEncoder } from '@webxr-jp/texture-compression'\nimport { okAsync, ResultAsync } from 'neverthrow'\nimport { Scene } from 'three'\nimport { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js'\nimport { VRMExporterPlugin } from '../exporter'\nimport type { ExportVRMError, ExportVRMOptions } from '../types'\n\n/**\n * VRM をバイナリとしてエクスポートする\n *\n * @param vrm - エクスポート対象の VRM\n * @param options - エクスポートオプション\n * @returns ArrayBuffer (バイナリデータ) またはエラー\n *\n * @example\n * ```typescript\n * const result = await exportVRM(vrm)\n *\n * if (result.isOk()) {\n * // ブラウザでダウンロード\n * const blob = new Blob([result.value], { type: 'application/octet-stream' })\n * const url = URL.createObjectURL(blob)\n * // ...\n *\n * // Node.js でファイル書き出し\n * fs.writeFileSync('output.vrm', Buffer.from(result.value))\n * }\n * ```\n */\nexport function exportVRM(\n vrm: VRM,\n options: ExportVRMOptions = {},\n): ResultAsync<ArrayBuffer, ExportVRMError> {\n const { binary = true, textureCompression } = options\n\n // テクスチャ圧縮が有効な場合、先に WASM エンコーダーを初期化\n const initPromise: ResultAsync<void, ExportVRMError> = textureCompression\n ? initBasisEncoder()\n .map(() => undefined)\n .mapErr((err) => ({\n type: 'EXPORT_FAILED' as const,\n message: `Basis WASM 初期化に失敗: ${err.message}`,\n }))\n : okAsync(undefined)\n\n return initPromise.andThen(() =>\n ResultAsync.fromPromise(\n new Promise<ArrayBuffer>((resolve, reject) => {\n // SpringBone を初期状態にリセット\n vrm.springBoneManager?.reset()\n vrm.springBoneManager?.setInitState()\n\n const exporter = new GLTFExporter()\n\n // MToonAtlasExporterPlugin を登録し、圧縮オプションを設定\n exporter.register((writer) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const plugin = new MToonAtlasExporterPlugin(writer as any)\n if (textureCompression) {\n plugin.setTextureCompressionOptions(textureCompression)\n }\n return plugin\n })\n\n exporter.register((writer) => {\n const plugin = new VRMExporterPlugin(writer)\n plugin.setVRM(vrm)\n return plugin\n })\n\n // vrm.scene の子要素を Scene に直接追加してエクスポート\n // VRMHumanoidRig と VRMExpression はランタイム専用なので除外\n const exportScene = new Scene()\n const children = [...vrm.scene.children].filter(\n (child) =>\n child.name !== 'VRMHumanoidRig' &&\n !child.name.startsWith('VRMExpression'),\n )\n children.forEach((child) => exportScene.add(child))\n\n exporter.parse(\n exportScene,\n (result) => {\n // エクスポート後、子要素を元の vrm.scene に戻す\n children.forEach((child) => vrm.scene.add(child))\n\n try {\n if (result instanceof ArrayBuffer) {\n resolve(result)\n } else {\n // JSON 出力の場合\n const jsonString = JSON.stringify(result)\n const encoder = new TextEncoder()\n resolve(encoder.encode(jsonString).buffer as ArrayBuffer)\n }\n } catch (err) {\n reject(err)\n }\n },\n (error) => {\n // エラー時も子要素を元に戻す\n children.forEach((child) => vrm.scene.add(child))\n reject(error)\n },\n {\n binary,\n trs: false,\n onlyVisible: true,\n },\n )\n }),\n (error): ExportVRMError => ({\n type: 'EXPORT_FAILED',\n message: `Failed to export VRM: ${String(error)}`,\n }),\n ),\n )\n}\n","/**\n * VRM ロード機能\n * URL / File / Blob / ArrayBuffer から VRM を読み込む\n */\nimport type { VRM } from '@pixiv/three-vrm'\nimport { VRMLoaderPlugin } from '@pixiv/three-vrm'\nimport { MToonAtlasLoaderPlugin } from '@webxr-jp/mtoon-atlas'\nimport { ResultAsync } from 'neverthrow'\nimport { WebGLRenderer } from 'three'\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'\nimport { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js'\nimport type { VRMLoaderError } from '../types'\n\n/**\n * VRM ソースの型\n * URL文字列、File、Blob、ArrayBuffer を受け付ける\n */\nexport type VRMSource = string | File | Blob | ArrayBuffer\n\n// KTX2Loader のシングルトンインスタンス\n// WebGLRenderer との関連付けが必要なため、遅延初期化\nlet ktx2LoaderInstance: KTX2Loader | null = null\n\n/**\n * KTX2Loader を取得または初期化する\n * ブラウザ環境でのみ動作(WebGL コンテキストが必要)\n */\nfunction getKTX2Loader(): KTX2Loader | null {\n if (ktx2LoaderInstance) {\n return ktx2LoaderInstance\n }\n\n // ブラウザ環境チェック\n if (\n typeof document === 'undefined' ||\n typeof WebGLRenderingContext === 'undefined'\n ) {\n return null\n }\n\n try {\n // KTX2Loader の初期化には WebGL コンテキストが必要\n // 一時的な canvas から WebGLRenderer を作成\n const canvas = document.createElement('canvas')\n const gl = canvas.getContext('webgl2')\n\n if (!gl) {\n console.warn(\n 'WebGL2 がサポートされていません。KTX2 テクスチャは読み込めません。',\n )\n return null\n }\n\n const renderer = new WebGLRenderer({\n canvas,\n context: gl,\n })\n\n ktx2LoaderInstance = new KTX2Loader()\n // Basis Universal transcoder のパス(CDN から読み込み)\n ktx2LoaderInstance.setTranscoderPath(\n 'https://cdn.jsdelivr.net/npm/three@0.175.0/examples/jsm/libs/basis/',\n )\n ktx2LoaderInstance.detectSupport(renderer)\n\n // eslint-disable-next-line no-console\n console.log('KTX2Loader 初期化完了')\n\n // 一時的な renderer を破棄\n renderer.dispose()\n\n return ktx2LoaderInstance\n } catch (error) {\n console.warn(\n 'KTX2Loader の初期化に失敗しました。KTX2 テクスチャは読み込めません。',\n error,\n )\n return null\n }\n}\n\n/**\n * VRM を読み込む\n *\n * @param source - VRM ソース (URL文字列 / File / Blob / ArrayBuffer)\n * @returns VRM オブジェクトまたはエラー\n *\n * @example\n * ```typescript\n * // URL から読み込み\n * const result = await loadVRM('/path/to/model.vrm')\n *\n * // File から読み込み\n * const result = await loadVRM(file)\n *\n * // ArrayBuffer から読み込み\n * const result = await loadVRM(arrayBuffer)\n * ```\n */\nexport function loadVRM(source: VRMSource): ResultAsync<VRM, VRMLoaderError> {\n return ResultAsync.fromPromise(\n (async () => {\n const loader = new GLTFLoader()\n\n // KTX2Loader を設定(KTX2 テクスチャのサポート)\n const ktx2Loader = getKTX2Loader()\n if (ktx2Loader) {\n loader.setKTX2Loader(ktx2Loader)\n }\n\n loader.register((parser) => new VRMLoaderPlugin(parser))\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loader.register((parser) => new MToonAtlasLoaderPlugin(parser as any))\n\n let gltf\n let blobUrl: string | null = null\n\n try {\n if (typeof source === 'string') {\n // URL から読み込み\n gltf = await loader.loadAsync(source)\n } else if (source instanceof ArrayBuffer) {\n // ArrayBuffer から読み込み\n // 空のパスを渡すとGLTFLoaderが相対パスを解決できないため、\n // Blobに変換してURLを作成\n const blob = new Blob([source], { type: 'model/gltf-binary' })\n blobUrl = URL.createObjectURL(blob)\n gltf = await loader.loadAsync(blobUrl)\n } else {\n // File / Blob から読み込み\n blobUrl = URL.createObjectURL(source)\n gltf = await loader.loadAsync(blobUrl)\n }\n\n const vrm = gltf.userData.vrm as VRM | undefined\n\n if (!vrm) {\n throw new Error('VRM data not found in loaded file')\n }\n\n return vrm\n } finally {\n // すべての読み込みが完了した後にblob URLを解放\n // Note: GLTFLoaderはloadAsync完了時点ですべてのリソースをメモリにロード済み\n if (blobUrl) {\n URL.revokeObjectURL(blobUrl)\n }\n }\n })(),\n (error): VRMLoaderError => ({\n type: 'VRM_LOAD_FAILED',\n message: `Failed to load VRM: ${String(error)}`,\n }),\n )\n}\n"]}
|