Help with Barnes-hut

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?

3 Likes

If the force was done with positions instead of LineForce would it perform better, without or with collision?

Using Roblox’s physics for this would be insanely laggy if you intend to have many objects. Try to reduce the amount of interaction your objects have with the physics system as much as you can. There are multiple topics on how to do this on the DevForum and Roblox has an article on this.

So using positions would probably be best. Just update the positions as little as you can get away with and tween between the current and updated points.

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?

I’ve never even heard of Barnes-Hut until today! It’s super interesting something I definitely will look into further at some point. I did notice it used Octrees which I have heard of and I would suggest you check out @Quenty’s Octree module. I think it’s definitely possible if you optimize and don’t have too many parts being updated at once, but there is some limit when it comes to Roblox on the scale of these types of things because you don’t have as much control over how data is stored.

What would it be like to implement LeapFrog for this code?

Could you explain what LeapFrog is? I’m not sure what you meant by this.

3 Likes

Thank you for the informations!

Yeah, the Barnes-Hut is something I hardly find
but I love watching videos that simulate interactions between galaxies

LeapFrog is an algorithm that simplifies the simulation timestep and guarantees energy conservation, which seems to make it more stable and allow time reversal, from what I understand
it’s really a little complicated

more information on this site
https://anaroxanapop.github.io/behalf/#Code

1 Like