How do I translate a set of cframe values in world-space and convert them into the object-space for a Bone Chain?

Hello, just a heads up; this will require some basic knowledge of Bones & CFrame

I have a part connected to a chain of bones which I used @EgoMoose’s FABRIK module to calculate the required orientation of these chains to make this effect

The code works excellent from what you can see in the video, I’m setting the calculated coordinates from the module into the Bone’s WorldCFrame; but I later realize this takes a huge toll on performance for whatever reason, which means I must be manipulating the CFrame property instead of the Bones.

I thought this would be as simple as transferring the world cframe into object space with the ToObjectSpace method which is how my code looks now;

This is how the code below makes the chain system look: here

The code used to calculate the joints from the module
local origin = + ( - chain.origin).Unit * chain.totallength/2,
	for i, _ in next, chain.joints do
		local n = i < #chain.joints and i + 1; if n then
			local v = chain.joints[n] - chain.joints[i]
			local cframe =[i] + v/2, chain.joints[n]) -- The World CFrame of the current bone.
            local offset = cframe:ToObjectSpace(origin) --> Should've turned the World CFrame into local orientation, but it's not quite exactly similar
            -- bones[i].WorldCFrame = cframe --> this works but makes it super laggy
             bones[i].CFrame = offset

After more experimenting done, I notice that the Roblox bone system takes CFrame influence of it’s parent Bone + the offset cframe of the Bone itself; which is calculated by:

local WorldCFrame = bone_attachment.Parent.CFrame * bone_attachment.CFrame

this can be seen here

Using this information, how can I build the local orientation needed to displace the bone’s CFrame by to get the same effect?


Before we even get to the CFraming, I’m going to need sauce on this:

Have you done any benchmarking? With the preferable method I learnt now with os.clock()

Sample benchmarking code
local startTime = os.clock()

for i=1,10000 do
--Put your test code here

local deltaTime = os.clock() - startTime
print("Elapsed time method 1: " .. deltaTime)

Otherwise, yeah you got the formula correctly, but you haven’t applied ToObjectSpace correctly since you will need to inverse the parent CFrame, and instead you have inversed the goalCFrame instead so try this out I guess?

			local goalCFrame =[i] + v/2, chain.joints[n]) -- The World CFrame of the current bone.
            local offset = bones[i].Parent.CFrame:ToObjectSpace(goalCFrame) --> Should've turned the World CFrame into local orientation, but it's not quite exactly similar
             bones[i].CFrame = offset

I’m not sure what the cause of the lag is. It could just be due to the constant resizing of the bone geometry which Roblox kinda sucks at judging from the resizing/changing geometry of base parts which I’m assuming should apply to this situation as well.

Otherwise, if you want to try a different algorithm I’m working on CCDIK which I gave out in this scripting support file: CCDIK rotation troubles. Just if you are curious, but I believe FABRIK should already be light weight without constraints as-is from my experiences with using it for Motor6D’s which you can see in my project.


yo @dthecoolest! I was looking into your Motor6D to IK solver not that long ago, pretty nice experimentation you’ve been doing, hows the CCDIK project coming along?

After testing the performance using your code, the time elapsed looks normal I think it is just the way roblox calculates the WorldCFrame because even when you index that property, it lags stupendously.

I’ll be experimenting with your suggested cframe, although it currently looks funky after applying your suggestion, it looks like it’s getting closer to the result; I have more adjustments to make. Thank you for gearing me towards the right direction for a solution!


Thank you, @dthecoolest. I was successfully able to translate the orientation through some visual works and object-space manipulation. Check out the result using CFrame instead of “WorldCFrame” (which also eliminate the lag!)

Result Video