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

How do I tell if a lookVector points to right/left of another one?

Asked by
Supint 60
9 years ago
if VEC1.X > VEC2.X then
    bool = true
else
    bool = false
end

That's what I'm trying right now. VEC1 and VEC2 are lookVectors. It works mostly, but the true and false values seem to switch like four times over a 360 rotation. I think I know why, but I can't find an alternative. I haven't taken trig yet. qq

I think someone may have suggested something about toObjectSpace() but I'm not sure how to use it.

1 answer

Log in to vote
3
Answered by
Unclear 1776 Moderation Voter
9 years ago

Vectors do not have enough orientation information for you to determine a right or a left. To do this, we will need two references to CFrames rather than vectors. For simplicity, I will use cfSource and cfOffsetas variables referencing our two CFrames. We are trying to find if cfOffset is to the left or right of cfSource.

We will be using a special operation called the dot product to do this. I will not be explaining everything about the dot product, but essentially in Lua the dot product between two Vector3s would look like this:

function dotProduct(v1, v2)
    return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z
end

As you can see, the dot product takes like dimensions of each vector and multiplies them together, then adds up all of those products. A property of the dot product is that the smallest angle between the two vectors is less than 180 degrees or half pi when the result is positive and greater than 180 degrees or half pi when the result is negative. Naturally, if the result is zero then the two vectors form a right angle with each other.

With this knowledge, we can make one vector point to the relative right of cfSource and make another vector be the lookVector of cfOffset then find the dot product to see if cfOffset is a bit to the right, a bit to the left, or in the middle. We already have the lookVector of cfOffset with cfOffset.lookVector, so it comes down to finding a vector that points to the relative right of cfSource.

If you know about how CFrames are constructed, this is a trivial task. The CFrame, for simplicity's sake, is a 3x4 matrix that looks like the following:

xx yx zx px
xy yy zy py
xz yz zz pz

If you know a bit of linear algebra, you will know that matrices are just a bunch of vectors put side by side. Each column of a matrix is a vector of its own, like so...

xx | yx | zx | px
xy | yy | zy | py
xz | yz | zz | pz

The first column is a vector that points to the relative right of the orientation. The second column is a vector that points to the relative top of the orientation. The third column is a vector that points to the relative back of the orientation. The last column is the position vector of the orientation.

So, we already have our relative right vector if we just use the components method!

local px, py, pz,
    xx, yx, zx,
    xy, yy, zy,
    xz, yz, zz = cfSource:components()
local cfSourceRelativeRight = Vector3.new(xx, xy, xz)

Now that we have our two vectors, we can create a function that does all of this for us for any two CFrames. It will return 1 if the second CFrame is to the right of the first, -1 if it is to the left, and 0 if it is in the middle.

function isRight(cfSource, cfOffset)
    local px, py, pz,
        xx, yx, zx,
        xy, yy, zy,
        xz, yz, zz       = cfSource:components()
    local lookVector     = cfOffset.lookVector
    local dotProduct     = xx*lookVector.x + xy*lookVector.y + xz*lookVector.z
    if dotProduct < 0 then
        return -1
    elseif dotProduct > 0 then
        return 1
    else
        return 0
    end
end
0
You fixed it! That was also very informational, thank you. Supint 60 — 9y
Ad

Answer this question