How to get a unit vector relative to another unit vector?

image
In the depiction above, the blue dotted line represents the world origin, and the pink line represents a unit vector of (-0.707, 0.707). The yellow line represents a second unit vector. Relative to the world origin, the line’s vector can be read as (0.707, 0.707). Relative to the pink vector however, it can be read as (0, 1). How can I do this via script?

this seems to be an application of cross product (because dot product cannot know which direction)

denote angle as their angle difference counting clockwise or anti-clockwise depend on the coordinate system
cross(pink, yellow) = |pink| |yellow| sin(angle)
because they are unit vectors, |pink| = |yellow| = 1, so
cross(pink, yellow) = sin(angle)
angle = arcsin( cross(pink, yellow) )

from your diagram, if the angle = 90 degrees
cos(angle) = 0, sin(angle) = 1
so our coordinates is (x, y) = ( cos(angle), sin(angle) )

if the angle = -90 degrees (because of coordinate system it measures as negative)
cos(angle) = 0, sin(angle) = -1
so in this coordinate system, (x, y) = ( cos(angle), -sin(angle) )

1 Like

I thought Cross() returns a vector3? where are you getting the angle from

1 Like

image

local function Cross(a,b)
	return a.x * b.y - a.y * b.x
end
2 Likes

I put together this function:

--fixes NaNs
local function breakNaN(num)
	return (num == num and num) or 0
end

--returns the cross between two vectors
local function Cross(a,b)
	return a.x * b.y - a.y * b.x
end

--returns the vector a relative to another vector b
function getRelativeVector(a, b)
	local vectorA = Vector2.new(a.X, a.Z)
	local vectorB = Vector2.new(b.X, b.Z)
	local angle = Cross(vectorB, vectorA)
	return Vector3.new(breakNaN(math.cos(angle)), 0, -breakNaN(math.sin(angle)) )
end

It doesnt seem to be working as expected.

In this test, I have two parts set up like so:

image

when I use the above function to get the first’s forward vector relative to the second, i get: (1, 0, -0)
Now when I do this:

image

The expected output should be (0, 0, 1). Instead I get (0.5403022, 0, 0.84147095)
What might be wrong here?

1 Like

remember arcsin the cross for the angle
local angle = math.asin(Cross(a, b))

1 Like

Thank you! lastly, the X component seems to be only returning in a range of 0 to 1. When pointing forward this function returns 1 for the x component, but it also returns 1 for the x component when pointing backward. While rotating the part, this number can be seen approaching 1 in both directions.

1 Like

hmm. may be print out the angle, see if it make sense.
i would expect it be from -pi to pi, or from 0 to 2*pi.

1 Like

the angle seems to range from -pi/2 when pointing to the left to pi/2 when pointing right, but the value never exceeds pi/2. When pointing forward or backward, the angle gravitates toward 0

i am also confused :sweat_smile: not a good day to use math.
maybe someone could correct my mistake

2 Likes
local unitVector = -- your unit vector.

local CFrameOfVector = CFrame.new(Vector3.zero,unitVector)

-- just do: CFrameOfVector.LookVector,CFrameOfVector.UpVector,CFrameOfVector.RightVector
-- if you want to do it using another vector then do:
local relativeVector = CFrameOfVector:VectorToObjectSpace(newVector)
1 Like

This worked! thank you, I will be going with this!