DWG NO. CD-2026-009
SCALE — NTS
SHEET 9 / 9

3D UPGRADE GUIDE — VIRTUAL COMPANY × REACT-THREE-FIBER

バーチャル製作所を、
本物の3Dオフィスにする。

CSSで作った2.5D版(virtual-company.jsx)を、react-three-fiber による本物の3D空間に進化させる構成ガイドです。 Agent Office(ブラック製作所)で培った react-three-fiber の資産がそのまま流用できるため、 ゼロからではなく「見た目の載せ替え」として設計します。 鍵は、シミュレーション(状態)と描画(3D)を最初から分離しておくことです。

A-1 / ROADMAP

2.5D → 3D の3段階

一気に作り込まず、動くものを保ったまま段階的に載せ替えます。各段階で「デモに使える状態」を維持するのがポイントです。

S1

CSS 2.5D(現状)

virtual-company.jsx。CSS transformとkeyframesによる疑似3D。状態管理とシナリオエンジンはこの段階で完成済みで、S2以降もそのまま使い回します。 ✓ 完成済み
S3

glTFキャラ+実データ

キャラをglTFモデル+アニメーションクリップ(idle/typing/walk)に差し替え、GitHubの実稼働データを接続。「本物のAI会社の監視カメラ」が完成します。 → 発展(商品デモ品質)
B-1 / ARCHITECTURE

3D版のシステム構成 — 3層に分離する

「データ層」「状態層」「描画層」の3層構成にします。2.5D→3Dの載せ替えで交換するのは描画層だけ。これがS1の資産を無駄にしない設計です。

FIG. 1 — 3D バーチャル製作所 全体構成

📡 データ層 — 「何が起きているか」の供給源(2系統を切替可能に) A) シナリオエンジン(デモモード) buildScenario() のタイムライン再生。S1で実装済み。営業デモ・発信用 B) GitHubアダプタ(ライブモード) SHEET 8 の実環境(Actions実行状況・Issue・PR)をポーリング取得 → 同じイベント形式に変換 共通イベント形式 {type, agentId, payload} に統一 🧠 状態層 — Zustand ストア(2.5DでもR3Fでも同じものを参照) agents: {status, anim, target, bubble} tasks / board deliverables logs / events focus / phase camera: {mode, target} effects: {confetti, night} 🎬 描画層 — ここだけを 2.5D → R3F に交換する <Canvas>(react-three-fiber) <Office /> 床・壁・小物 <Desk /> ×5(机+PC) <AgentChar /> ×5 <FlyingDoc /> 書類演出 <CameraRig /> 追従 <Lights /> 昼夜切替 吹き出し・名札は drei の <Html> で3D空間内に配置(3D座標に追従するHTML) HTMLオーバーレイ(そのまま流用) ・社員ステータスパネル ・業務ボード / 成果物モニター ・活動ログ / 操作パネル → S1のJSXがほぼ無修正で使える

この構成の要:3Dキャラは状態を持ちません。Zustandストアの agents[id].anim("idle" | "typing" | "walk" | "jump")を見て再生するだけ。だからシナリオエンジンとGitHub実データを、描画コードを1行も変えずに切り替えられます。

B-2 / CORE CODE

S2の核になるコード(骨格)

R3F化の勘所は3つ:「状態→アニメの写像」「lerpによる移動」「Htmlによる吹き出し」。それぞれ最小の骨格を示します。

stores/company.js — 状態層(Zustand)import { create } from 'zustand'; export const useCompany = create((set) => ({ agents: { /* id: { status, anim: 'idle', target: [x,0,z], bubble } */ }, applyEvent: (ev) => set((s) => reducer(s, ev)), // デモ/実データ共通の入口 }));
components/AgentChar.jsx — 状態を見て動くキャラfunction AgentChar({ id, color }) { const agent = useCompany((s) => s.agents[id]); const ref = useRef(); // 毎フレーム: 目標地点へ lerp 移動(出勤・退勤が自動で滑らかに) useFrame((_, dt) => { ref.current.position.lerp( new THREE.Vector3(...agent.target), 1 - Math.pow(0.001, dt)); // typing中は小さく上下、walk中は左右に揺れる…をここで加算 if (agent.anim === 'typing') ref.current.position.y = Math.sin(performance.now() / 90) * 0.02; }); return ( <group ref={ref}> <mesh position={[0, 0.55, 0]}> {/* 頭 */} <sphereGeometry args={[0.22, 24, 24]} /> <meshStandardMaterial color="#F3D3AC" /> </mesh> <mesh position={[0, 0.18, 0]}> {/* 体(カプセル形はCylinder+Sphereで) */} <cylinderGeometry args={[0.2, 0.24, 0.4, 20]} /> <meshStandardMaterial color={color} /> </mesh> <Html position={[0, 1.05, 0]} center distanceFactor={7}> {agent.bubble && <div className="bubble">{agent.bubble}</div>} </Html> </group> ); }
App.jsx — Canvas と HTMLオーバーレイの二層構造<div className="screen"> <Canvas shadows camera={{ position: [6, 5, 8], fov: 40 }}> <ambientLight intensity={night ? 0.15 : 0.6} /> <directionalLight position={[5, 8, 4]} castShadow /> <Office /> {AGENTS.map((a) => <Desk key={a.id} {...a} />)} {AGENTS.map((a) => <AgentChar key={a.id} {...a} />)} <CameraRig /> {/* focus対象へ滑らかに寄るカメラ */} </Canvas> <StaffPanel /><BoardPanel /><MonitorPanel /><LogFeed /> {/* S1流用 */} </div>

注記:Claude.aiのアーティファクト上で試す場合は、react-three-fiberが使えないためthree.js(r128)を直接useEffectで組む形になります。本命はローカルのVSCode+Claude環境でR3F構成を組むこと。Agent Officeのプロジェクト構成が最良の参考実装です。

C-1 / EVENT MAPPING

イベント → 3D演出の対応表

これが「監視カメラ化」の設計図。デモモードでもGitHubライブモードでも、同じイベントが同じ演出を起こします。

イベント(共通形式) GitHubライブモードでの発生源 3D空間での演出
task.assigned Issueにラベル・担当者が付与 PMの机から担当者の机へ書類メッシュが放物線で飛ぶ+カメラが担当者へパン
agent.working claude.yml のワークフロー実行が in_progress キャラのanimが typing に。PC画面のエミッシブ発光が明滅、頭上に「考え中…」
deliverable.created コミットで docs/ にファイル追加 / Artifactアップロード 机から成果物モニターへ📄が飛び、チップがポップイン+効果音(任意)
review.requested PRが opened / review_requested レビュー担当の机にスポットライト点灯、animが typing に
review.approved PRが approved → merged 担当キャラが jump、ボードの該当タスクが完了色に遷移
watch.report 週次レポートIssueの起票(P5) 巡回担当が各机を歩いて回るパトロールアニメ → ボードにレポート掲示
day.completed その日の全ワークフロー完了 紙吹雪パーティクル → 全員が出口へ歩いて退勤 → ライトが夜モードへ減光
escalation(needs-human) needs-human ラベル付与(SHEET 8 P2) 赤い回転灯が点灯し、社長の机に「稟議書」が飛ぶ。あなたへの通知と連動

GitHubアダプタの実装:Cloud Run(またはミニPC)上の小さなFastAPIが、GitHub REST APIを30〜60秒間隔でポーリング(workflow runs / issues / PRs)し、差分を上記イベント形式に変換してWebSocket/SSEでフロントへ配信。認証トークンをブラウザに出さないための中継役も兼ねます。

C-2 / TECH STACK

採用ライブラリと役割

ライブラリ役割採用理由・メモ
react-three-fiber 3D描画のReact統合 three.jsをJSXで宣言的に書ける。Agent Officeで習熟済み=最大の資産
@react-three/drei 便利部品集 Html(吹き出し)/ OrbitControls / useGLTF / ContactShadows が主力
zustand 状態層 Canvas内外(3DとHTMLパネル)から同じストアを購読できるのが決定打
glTFモデル + Mixamo S3のキャラと動作 低ポリキャラにMixamoで idle/typing/walk のクリップを付与し useAnimations で切替アセットはライセンス(CC0等)を必ず確認
FastAPI + SSE GitHubアダプタ ポーリング→イベント変換→配信。Cloud Runでスケールtoゼロ運用(SHEET 3)
C-3 / BUILD ORDER

実装順序 — 週末5コマで組む

①(半日) Vite + R3F 環境を作り、床・5つの机・プリミティブキャラを静的に配置。OrbitControlsで眺められる状態に
②(半日) S1のシナリオエンジンとZustandストアを移植し、状態→アニメ写像(idle/typing/walk/jump)とlerp移動を実装
③(半日) dreiのHtmlで吹き出し・名札を3D空間に配置し、S1のHTMLパネル群をオーバーレイとして復活
④(半日) 演出強化: CameraRig(focus追従)、飛ぶ書類メッシュ、紙吹雪パーティクル、昼夜のライティング遷移
⑤(半日) GitHubアダプタ(FastAPIポーリング→SSE)を繋ぎ、デモ/ライブのモード切替スイッチを実装

Claude Codeへの依頼のコツ:この構成図とイベント対応表をそのままコンテキストに渡し、「①だけ」「②だけ」とコマ単位で依頼すると精度が上がります。まさに自分の商品(SHEET 8)で自分が顧客になる実践です。

D-1 / CAUTIONS

3D化の3つの注意

CHK-1

パフォーマンス予算を最初に決めるキャラ5体+小物なら余裕ですが、影・ポストエフェクトを盛ると急に重くなります。目標60fps・ドローコール100以下を先に決め、影はContactShadowsで済ませるのが低コストです。

CHK-2

3Dアセットのライセンス確認glTFモデル・アニメーションは商用デモに使う前提でCC0またはロイヤリティフリーを選び、出典を記録しておきます。MixamoはAdobeの利用規約の範囲で使用可能ですが、規約は変わり得るので採用時に確認を。

CHK-3

「動く3D」より「意味が伝わる3D」商品デモとしての価値は、クライアントが「AIが働いている様子が分かる」こと。演出を足すたびに「これは状態の理解を助けるか?」で判定し、装飾だけの動きは削る勇気を持つこと(needs-humanの赤色灯のような"意味のある演出"を優先)。

◀ 図面索引にもどる ◀ SHEET 8 商品仕様書 ① SHEET 11 20分共有キット ▶