Resizing a physics mesh dynamically

Hi Facepunch :v:

I’m trying to implement an asteroid mining system, and when mined an asteroid would be resized according to its remaining resources amount. I can’t find any (reliable) way to do that.

First, I save the asteroid’s original mesh. Then I modify vertices pos by multiplying it by the scale (a number) and apply the new mesh to the asteroid; here are the methods I’ve tested so far and issues I got from their usage:

  • PhysicsFromMesh: When executed clientside (for prediction, as seen in the Lua Rollercoaster Addon), instant client crash. Works fine serverside until two asteroids happen to collide with each other: server lags to death and eventually crashes.

local function deepCopy(tab)
	local toR = {}
	for k,v in pairs(tab) do
		if type(v) == "table" then
			toR[k] = deepCopy(v)
		elseif type(v) == "Vector" then
			toR[k] = Vector(v.x, v.y, v.z)
		else
			toR[k] = v
		end
	end
	return toR
end

function ENT:Initialize()
	self:PhysicsInit(SOLID_VPHYSICS)
	self:SetMoveType(MOVETYPE_VPHYSICS)
	self:SetSolid(SOLID_VPHYSICS)
	
	if self:GetPhysicsObject():IsValid() then
		self.originalMesh = self:GetPhysicsObject():GetMesh()
	end
end

function ENT:ResizePhysicsServer()
	if self:GetPhysicsObject():IsValid() then 
		local oldFrozen = self:GetPhysicsObject():IsMotionEnabled()
		self:GetPhysicsObject():EnableMotion(false)
		
		local s = self:GetAsteroidScale()
		local newMesh = {}
		for i, vertex in pairs( self.originalMesh ) do
			newMesh* = deepCopy(vertex)
			newMesh*.pos = vertex.pos * s
		end
		
		self:PhysicsFromMesh(newMesh)
		self:EnableCustomCollisions(true)

		self:GetPhysicsObject():EnableMotion(oldFrozen)
	end
end

  • PhysicsInitMultiConvex: Works fine on both server and client (prediction is great) but is VERY resource-consuming: server freezes for about 4 seconds when this is called

function ENT:Initialize()
	self:PhysicsInit(SOLID_VPHYSICS)
	self:SetMoveType(MOVETYPE_VPHYSICS)
	self:SetSolid(SOLID_VPHYSICS)
	
	if self:GetPhysicsObject():IsValid() then
		self.originalConvexes = self:GetPhysicsObject():GetMeshConvexes()
	end
end

function ENT:ResizePhysicsServer()
	if self:GetPhysicsObject():IsValid() then 
		local oldFrozen = self:GetPhysicsObject():IsMotionEnabled()
		self:GetPhysicsObject():EnableMotion(false)
		
		local s = self:GetAsteroidScale()
		local newConvexes = {}
		for i, convex in pairs( self.originalConvexes ) do
			newConvexes* = {}
			for j, vertex in pairs( convex ) do
				newConvexes*[j] = vertex.pos * s
			end
		end

		self:PhysicsInitMultiConvex(newConvexes)
		self:EnableCustomCollisions(true)

		self:GetPhysicsObject():EnableMotion(oldFrozen)
	end
end

Does anyone know how to solve those issues or an alternative method?

Anyone? :rolleyes:

Ok I found why PhysicsFromMesh made my client crash: AsteroidScale is a networked variable and defaults to 0 when the entity is created. Thus all vertices were (0,0,0) resulting in degenerate triangles and a crash. Ultra laggy collisions are not fixed though.
Now I’ve a problem with the asteroids’ movetype. When I use MOVETYPE_VPHYSICS the asteroid falls to the floor of the map (this appears to be a clientside effect as a friend of mine joined the game and saw the asteroid where it was supposed to be…). The asteroid goes back to its spawn position after a little while, players can grab it with the physgun but the beam points towards a random position (in fact, it’s the position of the asteroid when it was at the very bottom of the map).