Axolotleless

Level of detail script

Jan 31st, 2025
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.89 KB | None | 0 0
  1. do
  2.   local insert, remove = table.insert, table.remove
  3.   local LODSpecs = {}
  4.   local function bfind(t, v)
  5.     local a, b = 1, #t
  6.     while a <= b do
  7.       local u = floor((a + b) * 0.5)
  8.       local w = t[u].Sort
  9.       if v > w then
  10.         a = u + 1
  11.       elseif v < w then
  12.         b = u - 1
  13.       else
  14.         return u
  15.       end
  16.     end
  17.     return a
  18.   end
  19.   local function CalculateCenter(m)
  20.     local Center = v3b
  21.     local Children = m:GetChildren()
  22.     for _, Model in next, Children, nil do
  23.       if Model.ClassName == "Model" then
  24.         Center = Center + Model.PrimaryPart.Position
  25.       else
  26.         Center = Center + Model.Position
  27.       end
  28.     end
  29.     Center = Center / #Children
  30.     return Center
  31.   end
  32.   function LODSplitEach(m)
  33.     local Groups = {}
  34.     for _, Model in next, m:GetChildren() do
  35.       local Group = Instance.new("Model")
  36.       Model.Parent = Group
  37.       table.insert(Groups, Group)
  38.     end
  39.     for _, Model in next, Groups, nil do
  40.       Model.Parent = m
  41.     end
  42.   end
  43.   function LODSplitModel(m, n)
  44.     local w = floor(n ^ 0.5)
  45.     local Size = m:GetExtentsSize()
  46.     local Center = CalculateCenter(m)
  47.     local wx = floor(Size.X / w + 0.5)
  48.     local wz = floor(Size.Z / w + 0.5)
  49.     local Groups = {}
  50.     for _, Model in next, m:GetChildren() do
  51.       local p = Model.ClassName == "Model" and Model.PrimaryPart.Position or Model.Position
  52.       local rx = floor((p.X - Center.X) / wx) * wx
  53.       local rz = floor((p.Z - Center.Z) / wz) * wz
  54.       local v = ("%d/%d"):format(rx, rz)
  55.       local Group = Groups[v]
  56.       if not Group then
  57.         Group = Instance.new("Model")
  58.         Group.Parent = workspace
  59.         Group.Name = v
  60.         Groups[v] = Group
  61.       end
  62.       Model.Parent = Group
  63.     end
  64.     for _, Group in next, Groups, nil do
  65.       Group.Parent = m
  66.     end
  67.     return 0.25 * (wx + wz) * 1.4142135623730951
  68.   end
  69.   function LODAddModel(m, d)
  70.     local Parent = m.Parent
  71.     assert(Parent)
  72.     local Spec = {
  73.       Model = m,
  74.       Parent = Parent,
  75.       Center = CalculateCenter(m),
  76.       MinDist = d,
  77.       Loaded = true,
  78.       Locked = false
  79.     }
  80.     table.insert(LODSpecs, Spec)
  81.     return Spec
  82.   end
  83.   function LODAddModels(m, d)
  84.     local Specs = {}
  85.     for _, v in next, m:GetChildren() do
  86.       local Spec = LODAddModel(v, d)
  87.       table.insert(Specs, Spec)
  88.     end
  89.     return Specs
  90.   end
  91.   function LODRemoveModel(m)
  92.     for i = 1, #LODSpecs do
  93.       local Spec = LODSpecs[i]
  94.       if Spec.Model == m then
  95.         LODForceLoad(Spec)
  96.         Spec.Locked = true
  97.       end
  98.     end
  99.     return false
  100.   end
  101.   function LODForceLoad(Spec)
  102.     Spec.Model.Parent = Spec.Parent
  103.     Spec.Loaded = true
  104.     Spec.Locked = true
  105.   end
  106.   local LoadQueue = {}
  107.   local UnloadQueue = {}
  108.   function LODUpdateInterest(p)
  109.     local GFX = UserSettings():GetService("UserGameSettings").SavedQualityLevel
  110.     local Multiplier = GFX.Value > 0 and GFX.Value/2 or 2.5
  111.     LoadQueue = {}
  112.     UnloadQueue = {}
  113.     for _, Spec in next, LODSpecs, nil do
  114.       local d = (Spec.Center - p).magnitude
  115.       Spec.Sort = d
  116.       local ShouldBeLoaded = d < (Spec.MinDist*Multiplier)
  117.       if Spec.Locked then
  118.         ShouldBeLoaded = true
  119.       end
  120.       local Loaded = Spec.Loaded
  121.       if ShouldBeLoaded and not Loaded then
  122.         local i = bfind(LoadQueue, d)
  123.         insert(LoadQueue, i, Spec)
  124.       elseif not ShouldBeLoaded and Loaded then
  125.         local i = bfind(UnloadQueue, d)
  126.         insert(UnloadQueue, i, Spec)
  127.       end
  128.     end
  129.   end
  130.   local function ProcessQueue()
  131.     if #LoadQueue > 0 then
  132.       local Spec = remove(LoadQueue, 1)
  133.       Spec.Model.Parent = Spec.Parent
  134.       Spec.Loaded = true
  135.     end
  136.     if #UnloadQueue > 0 then
  137.       local Spec = remove(UnloadQueue)
  138.       Spec.Model.Parent = nil
  139.       Spec.Loaded = false
  140.     end
  141.   end
  142.   function LODStart(i)
  143.     ThreadLoopAdd(i, ProcessQueue,"LOD Queue Processing")
  144.   end
  145. end
Advertisement
Add Comment
Please, Sign In to add comment