garrysmod-requests
garrysmod-requests copied to clipboard
IK controls for lua
Details
I won't pretend to have even a beginning understanding on how the Inverse Kinematics system in Source actually works under the hood, but I do know that natively they're just controlled by sequences of a model which tells them how to behave. Even something as simple as being able to target an IK by name and direct it to a given position would be a huge game changer for all kinds of systems.
I specifically want it to just be able to add left hand markers to my weapon worldmodels so that I can have players gripping weapons properly instead of their hand/arm clipping through the weapon with the hl2 smg/ar2 IK position, but it has potential for a lot of other uses as well.
Create a model of a weapon with an attachment indicating the point of grip, make animation with ikrule attachment. Maybe it will work. Similar effects can be achieved with pose parameters. But all this requires new animations to be made. I doubt that there is an alternative. And i can't even imagine that something like this can be implemented in lua
To this end, I've been poking around random Lua IK libraries online and found this one I yoinked from a Roblox forum post. I've translated it to GLua and it works nicely.
local IK = {}
IK.__index = IK
function IK.new(bones, solverIterations, targetPosition)
local bonesLenght = {}
for i = 1, #bones do
if i >= #bones then
bonesLenght[i] = 0
else
bonesLenght[i] = (bones[i]:GetPos() - bones[i + 1]:GetPos()):Length()
end
end
return setmetatable(
{
bones = bones;
solverIterations = solverIterations;
targetPosition = targetPosition;
bonesLenght = bonesLenght;
},
IK
)
end
function IK:backward(forwardPosition)
local inversePosition = {}
for i = #forwardPosition, 1, -1 do
if i == #forwardPosition then
inversePosition[i] = self.targetPosition
else
local positionNext = inversePosition[i + 1]
inversePosition[i] = positionNext + ((forwardPosition[i] - positionNext):GetNormalized() * self.bonesLenght[i])
end
end
return inversePosition
end
function IK:forward(inversePosition)
local forwardPosition = {}
for i = 1, #inversePosition do
if i == 1 then
forwardPosition[i] = self.bones[1]:GetPos()
else
local positionPrevious = forwardPosition[i - 1]
forwardPosition[i] = positionPrevious + ((inversePosition[i] - positionPrevious):GetNormalized() * self.bonesLenght[i - 1])
end
end
return forwardPosition
end
function IK:solve()
local finalBonesPosition = {}
for i = 1, #self.bones do
finalBonesPosition[i] = self.bones[i]:GetPos()
end
for i = 1, self.solverIterations do
finalBonesPosition = self:forward(self:backward(finalBonesPosition))
end
for i = 1, #self.bones do
self.bones[i]:SetPos(finalBonesPosition[i])
end
end
Theoretically we should be able to do IK for players with this and SetBonePosition, alas I am not really sure what the math should be to make the player bones face the proper angles.
There's also a super jank alternative of using a ragdoll (at least for first person IK) lol
https://github.com/user-attachments/assets/0c5b2d82-4574-4c7e-ab19-225f65b3e498
To this end, I've been poking around random Lua IK libraries online and found this one I yoinked from a Roblox forum post. I've translated it to GLua and it works nicely.
Permission to steal & experiment with this?
To this end, I've been poking around random Lua IK libraries online and found this one I yoinked from a Roblox forum post. I've translated it to GLua and it works nicely.
Permission to steal & experiment with this?
Go right ahead, it was posted on a public Roblox forum thread and I just converted it to GLua in like 5 minutes.
@ZH-Hristov If you remove the local from the local IK = {} then you could actually turn that into a proper library that can be called globally. Maybe post that as its own repo, under accreditation of course.
Not really interested. Not my thing and I can't exactly do what I want to do with it.