Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How could I rotate around a certain point? [closed]

Asked by 10 years ago

How would I be able to rotate a part around a certain position?

For example: I don't want to rotate the part just around the center of the part. Say I wanted the point of rotation to be Vector3.new(0,10,0), but the part was at Vector3.new(10,0,0).

How could I accomplish this?

Locked by Thewsomeguy, adark, and Articulating

This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.

Why was this question closed?

2 answers

Log in to vote
1
Answered by 10 years ago

I made a model that you can take and examine. In the model, I used ArcHandles, but later in this answer I'll provide a general solution that takes two parts, a Rotating brick (that gets rotated) and a Rotation brick (the rotation point) as well as the desired angle CFrame to rotate.

Though I'm linking you to the demo I made, I'll be posting the script here as well in order to explain it. The model can be found here.

wait()
local offsetCF = nil
local lastAngle = 0

script.Parent.MouseButton1Down:connect(function()
    offsetCF = workspace.Rotation.CFrame:toObjectSpace(workspace.Part.CFrame)
    lastAngle = 0
    print "Button Down"
end)

script.Parent.MouseDrag:connect(function(axis, angle, radius)
    local ax, ay, az 
    ax = axis==Enum.Axis.X and angle - lastAngle or 0
    ay = axis==Enum.Axis.Y and angle - lastAngle or 0
    az = axis==Enum.Axis.Z and angle - lastAngle or 0
    workspace.Rotation.CFrame = workspace.Rotation.CFrame * 
                                        CFrame.Angles(ax, ay, az)
    workspace.Part.CFrame = workspace.Rotation.CFrame * offsetCF
    lastAngle = angle
    print "Dragging"
    print("Angle:", angle)
end)

Essentially, I have an offsetCF and a lastAngle variable at the top to store some "default values" that change each time a new rotation is made (as can be seen in the MouseButton1Down event). The offsetCF is the Rotating part's CFrame offset from the Rotation point's CFrame. The lastAngle needs to be saved each time you rotate the handles because of an issue further in the script.

Now, the MouseDrag part. The MouseDrag event of the ArcHandles passes the rotation Axis, the rotation Angle (relative to the STARTING point when we first click the mouse button), and the relative Radius (the mouse offset from the center of the ArcHandles? I'm not too sure, but I don't use it here, so ...). The first thing I do is grab the angle and store it into the appropriate angle value (ax for X-Axis, ay for Y-Axis, and az for Z-Axis). This ensures I'm rotating the desired part around the proper axis.

The actual rotation part is next. Due to the way ArcHandles work, this rotation strategy is different from the one you desire (but again, I'll supply you with the desired function at the end of this answer). For ArcHandles to work properly, the Adornee of the ArcHandles must be rotated, otherwise the ArcHandles GUI won't move at all. So we rotate the Rotation part by CFrame.Angles(ax, ay, az) -- remember, ax, ay, az are the angles to rotate along the respective axes.

Now that the Rotation part is rotated properly, we must now offset the Rotating part to assume its correct position. Because we already did the rotation on the Rotation part, all we need to do is offset our Rotating part from the Rotation part. Remember the offsetCF value we saved earlier? Yeah, that's what we use.

Due to the way ArcHandles work, I save the previous angle in a value so we can evaluate the correct angle in later MouseDrag events. Remember, the angle that is passed to the callback function is actually the angle from the STARTING mouse point, not from the new starting point due to rotating the Rotation part.

The solution you are looking for would look like this:

function Rotate(Part --[[ Part ]], RotationPoint --[[ Vector3 ]], Angles --[[ CFrame.Angles() ]] )
    local RotationCF =  CFrame.new(RotationPoint)
    local offsetCF = RotationCF:pointToObjectSpace(Part.CFrame)
    Part.CFrame = RotationCF * Angles * offsetCF
end

-- Example
Rotate( workspace.Part, workspace.Rotation, CFrame.Angles(0, 0, math.pi) )

Edit: Just realized you want to rotate around a Vector3 point. I updated the above script to accomplish that.

When dealing with CFrames, remember:

CFrame * CFrameAngle rotates at the center of CFrame.

CFrame * CFrame2 offsets CFrame by CFrame2.

[CFrame] * CFrameAngle * CFrame2 first rotates at the center of CFrame (or CFrame.new(0,0,0) if no CFrame is supplied) and then offsets the new CFrame value by CFrame2

I suggest you mess around with CFrames to get a better grasp on how the operations work. Good luck! :)

Ad
Log in to vote
-2
Answered by 10 years ago

Okay so what I think your trying to say is you want this?

nub = part1
point = part2
rotate = math.rad(190)

point.CFrame  = nub.CFrame + Vector3.new(0,10,0)
                * CFrame.Angles(0,rotate,0)

This is just a basic look. If you wanted to make a loop just add one. I believe this is the answer you were looking for. Also, if you don't know what nub stands for, I might just have to beat you. A nub isn't a noob. Any questions?