I am producing a game like Universe Sandbox and would like to implement Barnes-hut in my simulation but I’m not able to replicate the codes I find in articles for the Lua language
The simulation is very lagging and the objects are not considering the mass properly
In the article: The Barnes-Hut Galaxy Simulator
The code I already tried:
_G.G = 4.485
function Attract(obj1, obj2)
if obj1:IsA("Part") and obj2:IsA("Part") then
local distance = (obj1.Position - obj2.Position).Magnitude
local VectorForce = obj1:FindFirstChild("VectorForce"..obj2.Name) --This allows for multiple forces acting on one object. Unfortunately, it isn't optimized and deleted objects still affect other objects. Also there's no room for duplicate names
local Attachment = (obj1:FindFirstChildOfClass("Attachment") or Instance.new("Attachment", obj1))
if not VectorForce then
VectorForce = Instance.new("VectorForce", obj1)
VectorForce.Name = "VectorForce"..obj2.Name
VectorForce.Attachment0 = Attachment
VectorForce.ApplyAtCenterOfMass = true
VectorForce.RelativeTo = Enum.ActuatorRelativeTo.World
obj2.AncestryChanged:connect(function()
if not obj2:IsDescendantOf(game) then
VectorForce:Destroy()
end
end)
end
local objMassPriority = nil
local centerMass: number = 1 do
local massAll = {}
for _, object: Part in next, workspace.Folder:GetChildren() do
centerMass += object.Mass * centerMass
table.insert(massAll, object)
end
for _, objectMass in next, massAll do
if objMassPriority == nil then objMassPriority = objectMass end
if objectMass.Mass > objMassPriority.Mass then
objMassPriority = objectMass
end
end
end
if (obj2.Mass < objMassPriority.Mass) then
obj2 = objMassPriority
end
local mI, mJ = obj1.Mass, obj2.Mass
local rI, rJ = obj1.Position, obj2.Position
local G = _G.G
local d: Vector3 = (rI - rJ).Magnitude
local r = (obj1.Position - obj2.Position).Magnitude / centerMass
local unicode = {
['θ'] = d/r
}
local force = objMassPriority.Position - obj1.Position
VectorForce.Force = force
end
end
function AttractOthers(part, container)
if not container then container = workspace.Folder end
for _, part2 in ipairs(container:GetChildren()) do
if part2:IsA("Part") and part ~= part2 then
Attract(part, part2)
end
end
end
game:GetService("RunService").Heartbeat:Connect(function()
for _, part in ipairs(workspace.Folder:GetChildren()) do
if part:IsA("Part") then --Right now only handles Parts but can handle BaseParts. Can theoretically handle models, but you would need to edit it so it applies the force to the PrimaryPart and gets the entire mass of the model
AttractOthers(part)
end
end
end)
and now some doubts:
1- If the force was done with positions instead of LineForce would it perform better, without or with collision?
2- Is it possible to create a Barnes-hut for the motion we have in a gravity without dark matter, like in planets, solar systems, etc, having a circular orbit?
3- What would it be like to implement LeapFrog for this code?