Daikoku PA: lift mainline over the apron, rebuild both ramps
The PA ring road and the expressway mainline were both at ground level, so the ring parapet stood INSIDE the carriageway (measured -10.0 studs of vertical overlap: a wall in the middle of the road). Reference photos of the real Daikoku Futo PA show the expressway flying OVER the parking apron on pillars, with the PA at ground level and ramps climbing up to meet it. Rebuilt to match: - mainline lifted 38 studs through the junction, eased in/out (max 5.26% grade, within real expressway limits) - PA ring + apron stay at ground level; legacy PARingPillar props removed - both on/off ramps regraded over the full rise with smoothstep easing, segments overlapped 3 studs so wheels can't catch a seam, plus support pillars and edge kerbs where the deck is high Verified in-engine against built parts (tools/diag_daikoku.luau), not just source: clearance now +28.0 studs, both ramps continuous (max step 5.62, no gaps). tools/plot_daikoku.py renders the plan/section for comparison.
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
--[[
|
||||
diag_centrefix.luau -- test whether centreFix is applied in the wrong order.
|
||||
|
||||
The build does:
|
||||
shell:PivotTo(body.CFrame * heightCF * CFrame.Angles(0,yaw,0) * centreFix)
|
||||
|
||||
centreFix is a translation derived from the shell's CURRENT (unrotated)
|
||||
AABB centre. Placing it to the RIGHT of CFrame.Angles means it is expressed
|
||||
in the ROTATED frame, so a 180-degree yaw negates its X and Z. For the three
|
||||
shells with yaw ~= 0 this is harmless. For hatch_junk and hyper_x (yaw 180)
|
||||
it moves the shell by -2 * centreLocal instead of cancelling the offset.
|
||||
|
||||
This measures the resulting AABB-centre error for BOTH orderings, per shell.
|
||||
The numbers can come out either way -- if the current ordering is fine, both
|
||||
errors are ~0 and the hypothesis is dead.
|
||||
]]
|
||||
|
||||
local RS = game:GetService("ReplicatedStorage")
|
||||
local SSS = game:GetService("ServerScriptService")
|
||||
|
||||
local out = {}
|
||||
local function log(s)
|
||||
table.insert(out, s)
|
||||
end
|
||||
|
||||
local TARGETS = { "rx7_fc", "silv_s15", "gtr_r34", "hatch_junk", "hyper_x" }
|
||||
local shells = {}
|
||||
for _, root in ipairs({ RS, SSS, game:GetService("ServerStorage"), workspace }) do
|
||||
for _, d in ipairs(root:GetDescendants()) do
|
||||
if d:IsA("Model") and d:FindFirstChild("Wheels") and not shells[d.Name] then
|
||||
for _, t in ipairs(TARGETS) do
|
||||
if d.Name == t then
|
||||
shells[d.Name] = d
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Replicate trueAABB: min/max corner over all BaseParts, world space.
|
||||
local function trueAABB(model)
|
||||
local lo, hi
|
||||
for _, d in ipairs(model:GetDescendants()) do
|
||||
if d:IsA("BasePart") then
|
||||
local p = d.Position
|
||||
lo = lo and Vector3.new(math.min(lo.X, p.X), math.min(lo.Y, p.Y), math.min(lo.Z, p.Z)) or p
|
||||
hi = hi and Vector3.new(math.max(hi.X, p.X), math.max(hi.Y, p.Y), math.max(hi.Z, p.Z)) or p
|
||||
end
|
||||
end
|
||||
return lo, hi
|
||||
end
|
||||
|
||||
log(string.format("%-11s %-10s %-22s %-14s %s", "shell", "yaw", "centreLocal(x,z)", "CURRENT err", "FIXED err"))
|
||||
log(string.rep("-", 82))
|
||||
|
||||
for _, name in ipairs(TARGETS) do
|
||||
local shell = shells[name]
|
||||
if not shell then
|
||||
log(string.format("%-11s NOT FOUND", name))
|
||||
continue
|
||||
end
|
||||
|
||||
-- yaw the solver would compute
|
||||
local pivotInv = shell:GetPivot():Inverse()
|
||||
local wf = shell:FindFirstChild("Wheels")
|
||||
local fSum, fN, rSum, rN = Vector3.zero, 0, Vector3.zero, 0
|
||||
for _, w in ipairs(wf:GetChildren()) do
|
||||
local sum, n = Vector3.zero, 0
|
||||
if w:IsA("BasePart") then
|
||||
sum, n = w.Position, 1
|
||||
end
|
||||
for _, d in ipairs(w:GetDescendants()) do
|
||||
if d:IsA("BasePart") then
|
||||
sum, n = sum + d.Position, n + 1
|
||||
end
|
||||
end
|
||||
if n > 0 then
|
||||
local lp = pivotInv * (sum / n)
|
||||
local h = w.Name:sub(1, 1):upper()
|
||||
if h == "F" then
|
||||
fSum, fN = fSum + lp, fN + 1
|
||||
elseif h == "R" then
|
||||
rSum, rN = rSum + lp, rN + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
local yaw = 0
|
||||
if fN > 0 and rN > 0 then
|
||||
local nose = (fSum / fN) - (rSum / rN)
|
||||
if math.abs(nose.X) + math.abs(nose.Z) > 0.05 then
|
||||
yaw = -math.atan2(nose.X, -nose.Z)
|
||||
end
|
||||
end
|
||||
|
||||
local lo2, hi2 = trueAABB(shell)
|
||||
local centreLocal = shell:GetPivot():Inverse() * ((lo2 + hi2) / 2)
|
||||
local centreFix = CFrame.new(-centreLocal.X, 0, -centreLocal.Z)
|
||||
|
||||
-- Simulate both orderings against an identity body at the origin.
|
||||
local body = CFrame.new()
|
||||
local rot = CFrame.Angles(0, yaw, 0)
|
||||
|
||||
-- Where does the shell's AABB centre land, relative to the body axis?
|
||||
-- Model the centre as a point at centreLocal in the shell's pivot frame.
|
||||
local centrePoint = CFrame.new(centreLocal.X, 0, centreLocal.Z)
|
||||
|
||||
local currentCF = body * rot * centreFix
|
||||
local fixedCF = body * centreFix * rot -- translation applied BEFORE rotation
|
||||
|
||||
local curCentre = (currentCF * centrePoint).Position
|
||||
local fixCentre = (fixedCF * centrePoint).Position
|
||||
|
||||
local curErr = math.sqrt(curCentre.X ^ 2 + curCentre.Z ^ 2)
|
||||
local fixErr = math.sqrt(fixCentre.X ^ 2 + fixCentre.Z ^ 2)
|
||||
|
||||
log(
|
||||
string.format(
|
||||
"%-11s %-10s (%+.2f,%+.2f)%-8s %-14s %s",
|
||||
name,
|
||||
string.format("%+.0f deg", math.deg(yaw)),
|
||||
centreLocal.X,
|
||||
centreLocal.Z,
|
||||
"",
|
||||
string.format("%.3f", curErr),
|
||||
string.format("%.3f", fixErr)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
log("")
|
||||
log("err = how far the shell's AABB centre sits from the chassis axis (studs).")
|
||||
log("A large CURRENT err on the 180-degree shells with a near-zero FIXED err")
|
||||
log("confirms the ordering bug. If both columns match, the hypothesis is WRONG")
|
||||
log("and the offset is not the cause of the reversal.")
|
||||
|
||||
return table.concat(out, "\n")
|
||||
Reference in New Issue
Block a user