Roof Layer に入ると 住環境 OS の“外観の最終レイヤー” が完成する。
ここは Floor / Ceiling / Exterior と違って 形状の自由度が高いので、OS 設計として破綻しないためには「段階的生成」が必須になる。

ここでは、あなたの OS に完全に適合する 外周ポリゴン → 屋根メッシュ生成アルゴリズム を、
Roblox で実装しやすい形でまとめるね。


🏠 Roof Layer(屋根生成)

外周ポリゴン(outline)から屋根形状を自動生成するレイヤー

屋根は Structure Layer ではなく Exterior Layer の結果として決まる。
つまり:

  • 内部構造 → 外周ポリゴン
  • 外周ポリゴン → 屋根形状

という 二段階 OS が正しい。


🟦 ① 屋根の種類(OS 的に扱いやすい3種)

まずは OS として破綻しない「基本3タイプ」から始めるのが最適。

種類 特徴 実装難度 Roblox との相性
フラット屋根(Flat Roof) 平ら ★☆☆ 最も安定
片流れ屋根(Shed Roof) 一方向に傾斜 ★★☆ 実装簡単
切妻屋根(Gable Roof) 三角屋根 ★★★ 家らしさが出る

まずは Flat → Shed → Gable の順で OS を拡張するのが自然。


🟩 ② Flat Roof(最も安定・最初に実装すべき)

Flat Roof は 外周ポリゴンの上に 1 枚の Part を置くだけ。

外周ポリゴン → バウンディングボックスを取る

minX, maxX
minY, maxY

Roblox での生成

local function buildFlatRoof(outline, roofY, thickness)
    local minX, maxX = math.huge, -math.huge
    local minZ, maxZ = math.huge, -math.huge

    for _, p in ipairs(outline) do
        minX = math.min(minX, p[1])
        maxX = math.max(maxX, p[1])
        minZ = math.min(minZ, p[2])
        maxZ = math.max(maxZ, p[2])
    end

    local roof = Instance.new("Part")
    roof.Anchored = true
    roof.Size = Vector3.new(maxX - minX, thickness, maxZ - minZ)
    roof.Position = Vector3.new(
        (minX + maxX) / 2,
        roofY,
        (minZ + maxZ) / 2
    )
    roof.Name = "Roof_Flat"
    roof.Parent = workspace.Roof

    return roof
end

🟧 ③ Shed Roof(片流れ屋根)

片流れ屋根は 外周ポリゴンのバウンディングボックスを傾けるだけ。

傾斜角(例:10°)

local angle = math.rad(10)

Roblox での生成

roof.CFrame = roof.CFrame * CFrame.Angles(angle, 0, 0)

方向は:

  • north → Z 正方向に傾ける
  • south → Z 負方向
  • east → X 正方向
  • west → X 負方向

🟥 ④ Gable Roof(切妻屋根:三角屋根)

ここが Roof Layer の本番。

切妻屋根は:

  • 外周ポリゴンの「長辺」を探す
  • その長辺に対して垂直方向に屋根を折る
  • 2 枚の斜面 Part を生成する

① 長辺を探す

local function findLongestEdge(outline)
    local longest = 0
    local idx = 1
    for i = 1, #outline do
        local p1 = outline[i]
        local p2 = outline[(i % #outline) + 1]
        local dx = p2[1] - p1[1]
        local dz = p2[2] - p1[2]
        local dist = math.sqrt(dx*dx + dz*dz)
        if dist > longest then
            longest = dist
            idx = i
        end
    end
    return idx
end

② 長辺に垂直な方向を求める

→ 屋根の「棟(ridge)」の方向になる。

③ 2 枚の斜面 Part を生成

→ Flat Roof を 2 枚に分割して傾ける。


🟪 ⑤ Roblox 側:Roof Layer 全体コード(Flat + Shed + Gable)

local RoofBuilder = {}

function RoofBuilder.BuildRoof(exterior, roomHeight, floors, roofType)
    if workspace:FindFirstChild("Roof") then
        workspace.Roof:Destroy()
    end
    local folder = Instance.new("Folder")
    folder.Name = "Roof"
    folder.Parent = workspace

    local roofY = roomHeight * floors
    local outline = exterior.outline
    local thickness = 0.3

    if roofType == "flat" then
        return buildFlatRoof(outline, roofY, thickness)
    end

    if roofType == "shed" then
        local roof = buildFlatRoof(outline, roofY, thickness)
        roof.CFrame = roof.CFrame * CFrame.Angles(math.rad(10), 0, 0)
        return roof
    end

    if roofType == "gable" then
        return buildGableRoof(outline, roofY, thickness)
    end
end

return RoofBuilder

🎯 Roof Layer の OS 的ポイント

✔ 外周ポリゴンを使うので、内部構造が変わっても屋根が自動で変わる

→ Structure Layer と完全に連動

✔ Flat → Shed → Gable の順で拡張できる

→ OS の成長が自然

✔ Roblox 側は Part ベースで軽量

→ CSG 不要
→ 大規模建築でも軽い

✔ 屋根は Exterior Layer の「上位レイヤー」

→ 外壁が変わっても屋根は壊れない


次はどれを進める?

  • Gable Roof の完全実装(ridge line の計算)
  • 屋根材(テクスチャ)レイヤー
  • 軒(eaves)を追加する拡張
  • 屋根裏(attic)レイヤー
  • Roblox Plugin 化(GUI で屋根タイプ選択)

どのレイヤーでも続けられるよ。