Rotating a group of points based on a pivot point BUT the rotation has to be a vector direction

`local pivot = SequencePoints[1]`

``````for i,v in pairs(T) do
local newpivot = CFrame.new(pivot)
local offset  =  newpivot:toObjectSpace(v.CFrame)
newpivot = newpivot * CFrame.Angles(0, math.rad(10), 0)
v.CFrame = newpivot * offset -- Re-offset the part from the new rotation
end
``````

Right now I’m using this cool formula (above) I found in devforum. The problem with this is it rotates based on angles.

But I want it to pivot to a vector3 direction. use case? Im allowing players to make custom bullet paths, when they shoot I need to rotate the sequence points they made with there path in the direction of the gun barrel using GunBarrel.Front.CFrame.LookVector

Here’s what I mean by ‘rotating’ sequence points if you don’t have any clue what I’m saying.
https://gyazo.com/02c38ab74f87984fd236046beda11fd0
https://gyazo.com/9b1483c0f0182f13a66cc41449006aeb

(Watch the second one)

Try this function.

``````local function rotate(pivotTargetDir, originalPoints, pointParts)
local pivot = originalPoints[1]
local pivotRotationCf = CFrame.new(pivot, pivot+pivotTargetDir)
for i = 2, #originalPoints do
local originalPoint = originalPoints[i]
local posOffset = originalPoint-pivot
posOffset = Vector3.new(posOffset.X, posOffset.Y, -posOffset.Z)
local newPoint = pivotRotationCf*posOffset
pointParts[i].Position = newPoint
end
end
``````

Here’s some code I used to test it on a baseplate.

``````local Players = game:getService("Players")
local RunService = game:GetService("RunService")

local startPositions = {
Vector3.new(7, 0, 5),
Vector3.new(4, 0, 10),
Vector3.new(7, 0, 12),
Vector3.new(13, 0, 16),
Vector3.new(8, 0, 21)
}

local plr = Players.LocalPlayer
local mouse = plr:GetMouse()

local pointParts = {}

local pointPartFolder = Instance.new("Folder")
pointPartFolder.Parent = workspace

local function createPointPart(num, pos, parent)
local part = Instance.new("Part")
part.Name = "P"..num
part.Color = Color3.new(1, 1, 1)
part.Material = Enum.Material.SmoothPlastic
part.Shape = Enum.PartType.Ball
part.Anchored = true
part.Size = Vector3.new(1, 1, 1)
part.Position = pos
part.Parent = parent
return part
end

local function createPointParts(positions, parent)
for i, v in ipairs(positions) do
pointParts[i] = createPointPart(i, v, parent)
end
end

createPointParts(startPositions, pointPartFolder)

local pivot = startPositions[1]
RunService.RenderStepped:Connect(function()
rotate(mouse.Hit.Position-pivot, startPositions, pointParts)
end)``````
1 Like

https://gyazo.com/bbc5a3c6fa6f3244c37495e5290ae5a2

can you guess what this is? is it welding, oh no it isn’t it’s custom welding, using pivot poin vector rotations lol.

This will be very useful for my path making system. Thank you so much! Would you mind if you could explain a bit of the math, this part:

``````for i = 1, #originalPoints do
local originalPoint = originalPoints[i]
local posOffset = originalPoint-pivot
posOffset = Vector3.new(posOffset.X, posOffset.Y, -posOffset.Z)
local newPoint = pivotRotationCf*posOffset
pointParts[i].Position = newPoint
end
``````

Also I realised that I didn’t actually need to pivot around the first sequence point of the path, and instead pivot around the root, without your visual example I wouldn’t have realized this so thanks for that to. So now I pivot around the Root instead of the first sequence of the path.

Well, here’s some math explanation. `posOffset` is the offset in worldspace (relative to origin `CFrame`) between the pivot and another point. The calculations always use the same point coordinates to calculate the offset, instead of using the positions of the point parts. This means that the offsets used in the calculations are always the same.

The new calculated point, which is then set as the position of a point part, has to be offsetted based on a spesific direction. This can be achieved by `CFrame` calculations.

The functions creates a `CFrame` (`pivotRotationCf`) which’s `LookVector` points in the direction given to the function. Then it uses the offset that was calculated earlier to calculate the new point so that its offset relative to the new `CFrame` is the same as the offset of the corresponding original point relative to the origin `CFrame`. This calculation is done by multiplying the new `CFrame` with the offset, because multiplying a `CFrame` with a `Vector3` gives a world space position that, when turned into object space of the `CFrame`, would be equal to the `Vector3` in the multiplication. (The position of the original point relative to origin `CFrame` would be the same as the result of the calculation below, however, there is no reason to multiply the origin CFrame with a Vector, because you’ll just get that same Vector. But maybe this can help understand why I calculate the new point by multiplying the new `CFrame` with the offset.)

``````-- the result of this calculation is equal to posOffset
CFrame.new()*posOffset

-- the result of this calculation is equal to posOffset too.
CFrame.new():PointToObjectSpace(CFrame.new()*posOffset)

-- and so is the result of this
pivotRotationCf:PointToObjectSpace(pivotRotationCf*posOffset)
``````

The reason why `posOffset`’s `Z` is turned into its opposite is because the negative `Z` direction is the forward direction of a `CFrame`. This isn’t really necessary to do in the function as the correct direction could be properly calculated outside the function instead.

Hopefully this explanation makes sense .

1 Like