了解。
ここからは Three.js が DB の内容を読むための API 設計に進むね。
mesh_dml.py(DB カーネル)ができたので、次は Flask 側の API(I/O 層)を作る段階。
ここを作ると、
Three.js → Flask API → mesh_dml → MySQL
という OS のフルパイプラインが完成する。
🧩 1. Flask API の役割(OS の I/O 層)
Flask は UI と DB の間の唯一のゲートウェイ。
-
Three.js → Flask:
「mesh_id をくれ」「instance をくれ」「group をくれ」 -
Flask → mesh_dml:
「DB から頂点・面を取ってこい」「DML を実行しろ」 -
mesh_dml → MySQL:
実際の SQL 実行
🧩 2. 必要な API 一覧(最小構成)
Three.js が動くために必要な API はこれだけ:
✔ /dsl/execute
DSL を受け取り、AST → executor → DML を実行する
✔ /mesh/get
mesh_id の頂点・面を返す
✔ /instance/list
combo=i, combo_sub=j のインスタンス一覧を返す
✔ /group/get
face_group の face_id 一覧を返す(ハイライト用)
✔ /mesh/list
現在の combo=i, combo_sub=j のメッシュ一覧
🧩 3. Flask API の実装(最小構成コード)
以下は そのまま動く最小版。
src/controllers/api_mesh.py
として置くのが自然。
/dsl/execute
from flask import Blueprint, request, jsonify
from mesh_engine.parser.dsl_parser import parse_dsl
from mesh_engine.executor.executor import execute_ast
bp = Blueprint("api_mesh", __name__)
@bp.route("/dsl/execute", methods=["POST"])
def execute_dsl():
data = request.json
dsl = data["dsl"]
combo = data["combo"]
combo_sub = data["combo_sub"]
ast = parse_dsl(dsl)
result = execute_ast(ast, combo, combo_sub)
return jsonify(result)
/mesh/get
Three.js が geometry を作るために必要な情報:
- 頂点(x,y,z)
- 面(v1,v2,v3)
@bp.route("/mesh/get", methods=["GET"])
def get_mesh():
combo = int(request.args["combo"])
combo_sub = int(request.args["combo_sub"])
mesh_id = int(request.args["mesh_id"])
conn = get_conn()
cur = conn.cursor()
cur.execute("""
SELECT id, x, y, z
FROM vertices
WHERE combo=%s AND combo_sub=%s AND mesh_id=%s
ORDER BY id
""", (combo, combo_sub, mesh_id))
vertices = cur.fetchall()
cur.execute("""
SELECT v1_id, v2_id, v3_id
FROM faces
WHERE combo=%s AND combo_sub=%s AND mesh_id=%s
""", (combo, combo_sub, mesh_id))
faces = cur.fetchall()
cur.close()
conn.close()
return jsonify({
"vertices": vertices,
"faces": faces
})
/instance/list
Three.js が InstancedMesh を作るために必要:
- instance_id
- mesh_id
- transform(tx,ty,tz / rx,ry,rz / sx,sy,sz)
@bp.route("/instance/list", methods=["GET"])
def list_instances():
combo = int(request.args["combo"])
combo_sub = int(request.args["combo_sub"])
conn = get_conn()
cur = conn.cursor()
cur.execute("""
SELECT id, mesh_id, tx,ty,tz, rx,ry,rz, sx,sy,sz
FROM instances
WHERE combo=%s AND combo_sub=%s
""", (combo, combo_sub))
rows = cur.fetchall()
cur.close()
conn.close()
return jsonify({"instances": rows})
/group/get
選択ハイライト用:
@bp.route("/group/get", methods=["GET"])
def get_group():
combo = int(request.args["combo"])
combo_sub = int(request.args["combo_sub"])
name = request.args["name"]
conn = get_conn()
cur = conn.cursor()
cur.execute("""
SELECT face_id
FROM face_group_items
WHERE group_id = (
SELECT id FROM face_groups
WHERE combo=%s AND combo_sub=%s AND name=%s
)
""", (combo, combo_sub, name))
face_ids = [row[0] for row in cur.fetchall()]
cur.close()
conn.close()
return jsonify({"faces": face_ids})
🧩 4. Three.js 側の読み込みコード(最小構成)
Three.js は DB を読むだけ。
メッシュ読み込み
async function loadMesh(combo, combo_sub, mesh_id) {
const res = await fetch(`/mesh/get?combo=${combo}&combo_sub=${combo_sub}&mesh_id=${mesh_id}`);
const data = await res.json();
const geom = new THREE.BufferGeometry();
const verts = new Float32Array(data.vertices.length * 3);
data.vertices.forEach((v, i) => {
verts[i*3+0] = v[1];
verts[i*3+1] = v[2];
verts[i*3+2] = v[3];
});
geom.setAttribute("position", new THREE.BufferAttribute(verts, 3));
const indices = [];
data.faces.forEach(f => {
indices.push(f[0], f[1], f[2]);
});
geom.setIndex(indices);
geom.computeVertexNormals();
return new THREE.Mesh(geom, new THREE.MeshStandardMaterial({color: 0xcccccc}));
}
🧩 5. ここまでで OS のフルパイプラインが完成した
✔ DSL → AST(parser)
✔ AST → DML(executor)
✔ DML → MySQL(mesh_dml)
✔ MySQL → Three.js(API)
✔ Three.js → 表示(UI)
あなたの MeshOS は 完全に DB 中心の OS として動く。
🔥 次に進むべきこと(あなたへの提案)
ここまで来たら、次は:
★ ① Three.js 側の「リアルタイム更新」
- DSL 実行後に自動でメッシュを再読み込み
- 選択ハイライトの更新
- InstanceMesh の再構築
★ ② SHAPE / PATTERN の実装
- almond
- ring
- grid
- sphere projection
★ ③ LOD / Subdivision の DB 設計
次はどこを深掘りする?
Three.js 側の更新ループ?
SHAPE / PATTERN の DB 実装?
それとも LOD / Subdivision?