Transforming lookvector to be "aligned", and rotating other vectors based on that

Preface

Based on the direction the camera is facing, I need to align a vector (not the camera itself) to be based on the camera’s facing. For example, if the player’s camera is looking “mostly up” the outputted vector would be Vector3.new(0, 1, 0), and so on for all the other directions. I need to do this to both the look vector and up vector of the camera’s cframe.

After that, I need to rotate another vector based on the output of the above, on the up vector.

Problem

I do not know how to align the vector, nor do I know how to rotate a vector based on another vector. I made a very “garbage” function to align, but it seems to have edge-cases in which it doesn’t work, and the orientation of the output is slightly off.

The function:

local function GetDirectionalVector(vec)
	local max = math.max(vec.X, vec.Y, vec.Z)
	local min = math.abs(math.min(vec.X, vec.Y, vec.Z))
	
	if max > min then
		if vec.X >= vec.Y and vec.X >= vec.Z then -- vec.X greatest
			return Vector3.new(1, 0, 0)
		elseif vec.Y >= vec.X and vec.Y >= vec.Z then -- vec.Y greatest
			return Vector3.new(0, 1, 0)
		else -- vec.Z greatest
			return Vector3.new(0, 0, 1)
		end
	else
		if vec.X <= vec.Y and vec.X <= vec.Z then -- vec.X greatest
			return Vector3.new(-1, 0, 0)
		elseif vec.Y <= vec.X and vec.Y <= vec.Z then -- vec.Y greatest
			return Vector3.new(0, -1, 0)
		else -- vec.Z greatest
			return Vector3.new(0, 0, -1)
		end
	end
end

Question

How do I align the vector to an axis properly? And how do I rotate a vector based on another vector?

See CFrame | Roblox Creator Documentation

CFrame.fromAxisAngle ( Vector3 v,number r )
Creates a rotated CFrame from a Unit Vector3 and a rotation in radians

Use that to rotate a CFrame around your axis, then multiply that CFrame by the vector you wish to rotate.

1 Like

The SnapToAxis function is the function I put above, just reworded slightly. It has the same flaw where some cases will cause it to invert for some reason: The flaw I’ve been seeing was due to the part I was using to display what the vectors are internally was 90 degrees rotated by accident. Both my and your solution here works.

And the CFrame.fromAxisAngle solution is not what I am looking for either.

For more context:
Assume I have a vector that is relative to the “normal” look vector. I want to rotate it so it’s relative to the look vector of the camera, not based on some amount of degrees.

IE: If I have the “normal” vector that is facing up, and the look vector faces upwards, I want the resultant vector to be facing backwards. If the same look vector looks down, the resultant vector should be facing forwards.

Same for each direction, “normal” vector facing to the left, if the camera is looking “forward”, it should result in a vector facing left. If the camera is looking left, the result should be facing backwards.

Even more context / probably better wording of what I want:

Currently creating a movement system for a building game, I am moving the block based off of some vectors that are relative to “north”. I want to get the facing of the camera, and make it so those movement vectors aren’t relative to “north”, but instead the camera look vector.

I don’t want to rotate by x degrees/radians, I want to rotate a vector so it’s relative to another vector (ie the other vector would become “north”).

Here is how I would do it to align a vector to an axis vector

local function AngleBetween(vector1, vector2)
	return math.acos(math.clamp(vector1.Unit:Dot(vector2.Unit), -1, 1))
end

local Axises = {
	Vector3.new(1,0,0),
	Vector3.new(0,1,0),
	Vector3.new(0,0,1),
	Vector3.new(-1,0,0),
	Vector3.new(0,-1,0),
	Vector3.new(0,0,-1),
}

local function alignVectorToGlobalAxis(inputVector : Vector3)
	local angles = {}
	for i,axisVector in pairs(Axises) do
		angles[i] = AngleBetween(inputVector,axisVector)
	end

	local smallestAngle = math.huge
	local axisVector = Vector3.new()
	for i,angle in pairs(angles) do
		if angle < smallestAngle then
			smallestAngle = angle
			axisVector = Axises[i]
		end
	end
	return axisVector, smallestAngle
end

No idea what you mean by rotating a vector by another vector are you looking to rotate a vector around an axis?

So, based on a lookVector and upVector, I needed to determine which direction to move when WASD was pressed. The direction was determined as a Vector as well.

If the player is looking North, W must walk West, D must walk East, etc.
If the player is looking West, W must walk South, D must walk North, etc.

I also needed it for vertical.
Holding space while looking any direction except down or up moves the player upwards.
Holding space while looking down (with upvector facing north) moves the player north.
Holding space while looking down (with upvector facing west) moves the player west.

I feel like I’ve done an extremely poor job of conveying what I needed, and for that I’m sorry.

In any case, in classic me style, I’ve figured out a way to do it without using any sort of math at all.
It’s just a giant lookup table of vectors (over 100 lines long)…

Yes, I manually typed out 100 lines of MovementDirection[BasicDirections.Forward] = {...}.
Yes, I’d do it again if it meant avoiding Vector/CFrame math.

Hey thanks! I love reading more on here there’s always something to learn