Skip to content

Commit 5075ee7

Browse files
committed
VRMプレビューの表示位置の修正。
進捗を更新。
1 parent c4b52e8 commit 5075ee7

2 files changed

Lines changed: 50 additions & 10 deletions

File tree

PLAN.md

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -391,13 +391,43 @@ SLは身長200cm基準(VRM標準は170cm)のため倍率調整が必須。
391391
392392
今すぐ実装すべき順序:
393393
394-
1. VRM読込
395-
2. 身長スケール設定
396-
3. ボーンマッピング確認
397-
4. 顔制御設定(簡潔版)
398-
5. 指確認
399-
6. 3Dプレビュー
400-
7. エクスポート
394+
- [x] VRM読込
395+
- [x] 身長スケール設定
396+
- [x] ボーンマッピング確認
397+
- [x] 顔制御設定(簡潔版)
398+
- [x] 指確認
399+
- [x] 3Dプレビュー(three.js、バックエンド生成GLB表示)
400+
- [x] エクスポート(.gdb出力)
401+
402+
### 🧾 実装済み(2026-02-26時点)
403+
404+
- [x] Rustバックエンドの解析/変換コマンド(Tauri IPC・CLI)
405+
- [x] VRM拡張ベースのHumanoidボーン抽出(VRMC_vrm / VRMフォールバック)
406+
- [x] 必須ボーン不足・階層不整合・頂点数・テクスチャ警告のバリデーション表示
407+
- [x] テクスチャ自動縮小ポリシー(1024/2048)と出力後サイズレポート
408+
- [x] プロジェクト設定の保存/読込
409+
- [x] 2カラムUI(左:操作 / 右:プレビュー)とログ表示DOM
410+
411+
### 📌 残件(マイルストーン別)
412+
413+
#### v0.9(コア変換の完成)
414+
415+
- [ ] Aポーズ→Tポーズ補正の本実装(上腕回転補正+頂点逆補正)
416+
- [ ] inverseBindMatrices再生成の本実装
417+
- [ ] ウェイト再分配・joints最適化の本実装
418+
- [ ] ボーン階層の再構成(SL向け最終階層を明示的に構築)
419+
- [ ] Bento拡張ボーン(目・口・まぶた・指)の実運用レベル対応
420+
- [ ] Blender再読込~SLアップロードの最終検証フロー完了
421+
422+
#### v1.0(次バージョン)
423+
424+
- [ ] 尾・耳・羽の動作対応
425+
- [ ] プレビューの追加操作(グリッド/ライト/ワイヤーフレーム切替)
426+
- [ ] アニメーション自動取得・形式変換・再生テスト機能
427+
428+
#### v1.1(その次のバージョン)
429+
430+
- [ ] ヘッド抽出モード
401431
402432
---
403433

frontend/src/components/VrmPreview.vue

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const updateRendererSize = () => {
3333
const width = canvasHost.value.clientWidth;
3434
const height = Math.min(Math.max(canvasHost.value.clientHeight, 280), 420);
3535
36-
renderer.setSize(width, height, false);
36+
renderer.setSize(width, height, true);
3737
camera.aspect = width / height;
3838
camera.updateProjectionMatrix();
3939
};
@@ -66,18 +66,25 @@ const fitCameraToModel = (root: THREE.Object3D) => {
6666
return;
6767
}
6868
69+
root.updateMatrixWorld(true);
6970
const box = new THREE.Box3().setFromObject(root);
71+
if (box.isEmpty()) {
72+
return;
73+
}
74+
7075
const size = box.getSize(new THREE.Vector3());
7176
const center = box.getCenter(new THREE.Vector3());
7277
const maxSize = Math.max(size.x, size.y, size.z, 0.1);
7378
74-
camera.position.x = center.x;
79+
camera.position.set(center.x, center.y + maxSize * 0.4, center.z + maxSize * 1.8);
7580
camera.near = Math.max(maxSize / 200, 0.01);
7681
camera.far = Math.max(maxSize * 200, 1000);
7782
camera.updateProjectionMatrix();
83+
camera.lookAt(center);
7884
79-
controls.target.x = center.x;
85+
controls.target.copy(center);
8086
controls.update();
87+
controls.saveState();
8188
};
8289
8390
const loadPreviewModel = async (path: string, options: ConvertOptions) => {
@@ -163,6 +170,9 @@ onMounted(() => {
163170
controls.enableDamping = true;
164171
controls.minDistance = 0.2;
165172
controls.maxDistance = 50;
173+
controls.target.set(0, 0, 0);
174+
camera.lookAt(controls.target);
175+
controls.update();
166176
167177
const ambient = new THREE.HemisphereLight(0xffffff, 0x444444, 0.9);
168178
scene.add(ambient);

0 commit comments

Comments
 (0)