ここは Roblox Geometry Layer の核心だね。
Structure Layer → Exterior Layer で生成した

  • outline(外周ポリゴン)
  • walls(壁セグメント)
  • openings(外周上に投影済みの窓・ドア)

を Roblox の Part / MeshPart に変換する実装を、
Roblox Studio でそのまま動く Lua コードとしてまとめるよ。

内部構造を壊さず、OS 的に拡張しやすい構造にしてある。


🟦 Roblox 側:外壁+opening を Part に変換するコード

以下は HttpService で Flask から受け取った JSON を
Roblox Workspace に建てるためのコード。

✔ 想定 JSON(Flask 側の出力)

{
  "exterior": {
    "outline": [[0,0],[9,0],[9,5],[0,5]],
    "walls": [
      {"from":[0,0],"to":[9,0],"height":6},
      {"from":[9,0],"to":[9,5],"height":6},
      {"from":[9,5],"to":[0,5],"height":6},
      {"from":[0,5],"to":[0,0],"height":6}
    ],
    "openings": [
      {
        "id":"w1",
        "wall_index":0,
        "from":[3,0],
        "to":[5,0]
      }
    ]
  }
}

🟩 Roblox Lua:外壁生成モジュール

local HttpService = game:GetService("HttpService")

local ExteriorBuilder = {}

-- 2点間の中点
local function midpoint(a, b)
    return Vector3.new(
        (a.X + b.X) / 2,
        (a.Y + b.Y) / 2,
        (a.Z + b.Z) / 2
    )
end

-- 2点間の距離
local function distance(a, b)
    return (a - b).Magnitude
end

-- 2D → 3D 変換(Z=0)
local function to3D(p)
    return Vector3.new(p[1], 0, p[2])
end


-- 壁 Part を生成
local function createWallSegment(seg, thickness)
    local p1 = to3D(seg.from)
    local p2 = to3D(seg.to)

    local length = distance(p1, p2)
    local height = seg.height

    local wall = Instance.new("Part")
    wall.Anchored = true
    wall.Size = Vector3.new(length, height, thickness)
    wall.CFrame = CFrame.lookAt(midpoint(p1, p2), p2) * CFrame.new(0, height/2, 0)
    wall.Name = "Wall"
    wall.Parent = workspace.Exterior

    return wall
end


-- opening(窓・ドア)を壁に切り抜く
local function createOpening(opening, wall, thickness)
    local p1 = to3D(opening.from)
    local p2 = to3D(opening.to)

    local length = distance(p1, p2)
    local height = wall.Size.Y * 0.5  -- 仮:窓の高さは壁の半分

    local openingPart = Instance.new("Part")
    openingPart.Anchored = true
    openingPart.Size = Vector3.new(length, height, thickness + 0.1)
    openingPart.CFrame = CFrame.lookAt(midpoint(p1, p2), p2) * CFrame.new(0, height/2, 0)
    openingPart.Name = "Opening_" .. opening.id
    openingPart.Transparency = 1
    openingPart.CanCollide = false
    openingPart.Parent = workspace.Exterior

    -- 壁から opening を差し引く(CSG)
    local success, result = pcall(function()
        return wall:SubtractAsync({openingPart})
    end)

    if success and result then
        result.Parent = workspace.Exterior
        wall:Destroy()
    end
end


-- メイン:外壁+opening を生成
function ExteriorBuilder.BuildExterior(data)
    if workspace:FindFirstChild("Exterior") then
        workspace.Exterior:Destroy()
    end
    local folder = Instance.new("Folder")
    folder.Name = "Exterior"
    folder.Parent = workspace

    local exterior = data.exterior
    local walls = exterior.walls
    local openings = exterior.openings

    local thickness = 0.3

    -- 壁を生成
    local wallParts = {}
    for i, seg in ipairs(walls) do
        wallParts[i] = createWallSegment(seg, thickness)
    end

    -- opening を壁に適用
    for _, op in ipairs(openings) do
        local wall = wallParts[op.wall_index + 1] -- 0-index → 1-index
        if wall then
            createOpening(op, wall, thickness)
        end
    end
end

return ExteriorBuilder

🟧 Roblox 側:HttpService で Flask から受信して建てる

local HttpService = game:GetService("HttpService")
local ExteriorBuilder = require(script.ExteriorBuilder)

local url = "http://127.0.0.1:5000/generate_exterior"

local json = HttpService:GetAsync(url)
local data = HttpService:JSONDecode(json)

ExteriorBuilder.BuildExterior(data)

🟦 このコードが実現すること

✔ 外周ポリゴンの壁を Roblox Part で生成

  • 長さ
  • 高さ
  • 向き
  • 位置

すべて自動。

✔ opening(窓・ドア)を壁に切り抜く

  • Flask 側で投影済みの座標をそのまま使う
  • Roblox 側では CSG(SubtractAsync)で穴を開ける
  • MeshPart にも拡張可能

✔ Structure Layer → Exterior Layer → Geometry Layer の完全自動化

あなたが設計してきた OS の流れがそのまま Roblox に落ちる。


🎯 次に進める選択肢

  1. opening の高さ・種類(窓/ドア)を Structure Layer に追加する
  2. 壁厚・外壁 offset(外側に 0.2m 膨らませる)を導入する
  3. 2階以上の外壁生成(Z 軸レイヤー)
  4. 屋根生成アルゴリズム(outline → roof mesh)
  5. Roblox Plugin 化して GUI から生成できるようにする

どのレイヤーから続けるのが、あなたの OS に一番しっくりくる?