了解。
あなたが言う 「階層構造でメッシュを管理し、上位メッシュをシンボリックリンクし、拡大・細分化・編集できる」 という要求は、Three.jsでも完全に実現できる。
しかも、あなたの OS 的なレイヤー設計と非常に相性が良い。

ここでは、現実に動く・拡張しやすい・AI統合しやすい という3条件を満たす Three.js メッシュ階層OS を設計する。


🧩 Three.js で実現する「メッシュ階層OS」設計

1. 全体構造(OSレイヤー)

MeshOS
 ├─ NodeLayer(階層構造)
 │    ├─ MeshNode(実体)
 │    └─ LinkNode(シンボリックリンク)
 ├─ LODLayer(拡大・細分化)
 ├─ EditLayer(編集)
 └─ AILayer(構造生成)

あなたのアプリの思想をそのままWebに移植した形。


2. NodeLayer:階層構造の中核

■ MeshNode(実体ノード)

Three.js の Group をベースにする。

  • 子ノードを持てる
  • 自身のローカル変換(位置・回転・スケール)
  • メッシュ(BufferGeometry)を保持
class MeshNode extends THREE.Group {
  geometry?: THREE.BufferGeometry;
  material?: THREE.Material;

  constructor(geometry?: THREE.BufferGeometry, material?: THREE.Material) {
    super();
    this.geometry = geometry;
    this.material = material;
    if (geometry && material) {
      const mesh = new THREE.Mesh(geometry, material);
      this.add(mesh);
    }
  }
}

■ LinkNode(シンボリックリンク)

Three.js には「参照コピー」がないので、インスタンス化(InstanceMesh) を使う。

  • 元メッシュを参照
  • 変換だけ独立
  • 編集は元メッシュに反映
class LinkNode extends THREE.Group {
  constructor(public target: MeshNode) {
    super();
    const inst = new THREE.InstancedMesh(
      target.geometry!,
      target.material!,
      1
    );
    inst.setMatrixAt(0, new THREE.Matrix4());
    this.add(inst);
  }
}

これで「上位メッシュをリンクして配置」が可能。


3. LODLayer:拡大表示・細分化

■ LOD(Level of Detail)をノード単位で持つ

MeshNode に LOD を持たせる。

MeshNode
 ├─ lod0(粗い)
 ├─ lod1(中)
 └─ lod2(細かい)

Three.js の THREE.LOD を使うか、独自管理でもOK。

class MeshNode extends THREE.Group {
  lodLevels: THREE.Mesh[] = [];

  addLOD(mesh: THREE.Mesh, distance: number) {
    const lod = new THREE.LOD();
    lod.addLevel(mesh, distance);
    this.add(lod);
    this.lodLevels.push(mesh);
  }
}

■ 細分化(Subdivision)

Three.js には SubdivisionModifier がある。

import { SubdivisionModifier } from 'three/examples/jsm/modifiers/SubdivisionModifier.js';

function subdivide(geometry: THREE.BufferGeometry, level: number) {
  const modifier = new SubdivisionModifier(level);
  return modifier.modify(geometry.clone());
}

LOD2 を生成するときに使う。


4. EditLayer:編集機能

■ 選択

  • Raycaster で MeshNode を取得
  • LinkNode を選択した場合は target にフォーカス

■ 編集

  • TransformControls で位置・回転・スケール
  • 頂点編集は BufferGeometry の position を直接操作
function editVertex(geometry, index, newPos) {
  const pos = geometry.attributes.position;
  pos.setXYZ(index, newPos.x, newPos.y, newPos.z);
  pos.needsUpdate = true;
}

5. AILayer:構造生成との接続

AI が返す JSON を MeshNode の階層構造に変換する。

AI出力例

{
  "nodes": [
    {
      "id": "body",
      "primitive": "cylinder",
      "children": [
        { "id": "head", "primitive": "sphere" },
        { "id": "leg1", "link": "leg" },
        { "id": "leg2", "link": "leg" }
      ]
    },
    {
      "id": "leg",
      "primitive": "cylinder"
    }
  ]
}

ローダ

function loadStructure(json) {
  const nodeMap = new Map();

  // 実体ノードを先に作る
  json.nodes.forEach(n => {
    if (!n.link) {
      nodeMap.set(n.id, new MeshNode(createPrimitive(n.primitive)));
    }
  });

  // リンクノードを作る
  json.nodes.forEach(n => {
    if (n.link) {
      nodeMap.set(n.id, new LinkNode(nodeMap.get(n.link)));
    }
  });

  // 階層構造を構築
  json.nodes.forEach(n => {
    const node = nodeMap.get(n.id);
    if (n.children) {
      n.children.forEach(c => node.add(nodeMap.get(c.id)));
    }
  });

  return nodeMap.get("root") || [...nodeMap.values()][0];
}

6. これで何ができるか

✔ メッシュを階層構造で管理

UI でツリー表示可能。

✔ 上位メッシュをシンボリックリンク

脚6本の昆虫などが一瞬で作れる。

✔ 拡大表示

LOD 切り替えで細かい編集が可能。

✔ 細分化

SubdivisionModifier で局所的に細かくできる。

✔ 編集

TransformControls + 頂点編集で自由に変形。

✔ AI との接続

AI は「構造(ノードツリー)」だけ返せばよい。


次に詰めるべきはどれか選んでほしい

  1. 階層ノードのUI(ツリー表示+選択)
  2. LODの自動生成(AIがLOD0→LOD2を作る)
  3. Subdivisionの適用ルール(どの部位を細分化するか)
  4. AI JSON仕様の確定(StructureSpecの正式版)
  5. LinkNodeの最適化(InstanceMeshの扱い)

どれを深掘りしたいか教えてくれたら、次のレイヤーを設計するよ。