ここは 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 に落ちる。
🎯 次に進める選択肢
- opening の高さ・種類(窓/ドア)を Structure Layer に追加する
- 壁厚・外壁 offset(外側に 0.2m 膨らませる)を導入する
- 2階以上の外壁生成(Z 軸レイヤー)
- 屋根生成アルゴリズム(outline → roof mesh)
- Roblox Plugin 化して GUI から生成できるようにする
どのレイヤーから続けるのが、あなたの OS に一番しっくりくる?