Calculating the curvature between two positions

  1. What do you want to achieve?

I have an origin position and an end position which are used for bullets within my game. I would like to calculate the curve direction of the bullet using these two positional values.

To better help you understand what I would like to achieve, I have attached two reference images which I would like to achieve. These positions are three dimensional positions in the world space.

  1. What solutions have you tried so far?

I have tried a few solutions to this problem but most of them end up being inaccurate based on the orientation of the origin. I am not very good at the mathematical side of things.

Right

Left

3 Likes

Well there’s a few ways you could do this. You could add an initial velocity to the right/left side, then add an acceleration/force to change the velocity of the bullet as it travels toward the goal position. You would have to use your physics kinematic equations to make it simple.

You could also make an orbital circular path using a starting point, ending point, and a pivotal center. I recently answered something similar to this, you can check it out here:

2 Likes

Hey, thank you for your reply.

I don’t think you really understood the topic correctly. I appreciate your response, however the bullet is not a moving projectile and begins at the origin and ends at the destination.

What I want to accomplish is to create a function which will detect which way a bullet will curve based on the Origin and Destination of the bullet with a response of either ‘Left’ or ‘Right’.

I am not looking to modify the bullet at all, just detect the curvature. Would you happen to know how I could accomplish this?

4 Likes

I think it is like this

Print(bullet.CFrame)

Ensuer that the bullet is the part.

Or print((Bullet.CFrame - destination.CFrame).Magnitude)

Read about magnitude …

2 Likes

Hey.

Thank you for your insight.

I do not think this solution will work since you can only take away a Vector3 from a CFrame and vice versa with adding a Vector3 to a CFrame.

When the origin is coming from a different orientation the results will also be inaccurate.

2 Likes

You could use trigonometry to solve for the angle created between the bullet beam and the triangle formed by the lengths between the horizontal and vertical distances between both points.

image

Or… you could force a specific orientation to where the origin is always on the bottom (always aligned to one specific axis) and then compare the positions of both points. There are multiple ways to attack this problem, really.

2 Likes

Think of this as a problem where you’re figuring out the angle between the look vector of the origin, and the vector from the origin to the destination point.

In our model, O is the origin and D is the destination. We can calculate the angle theta, which is the angle between the look vector and the vector from O to D by calculating a plane P which both points lie in.

Since for this problem we need a normal vector that stays the same regardless of world orientation, let’s use the y axis as the normal vector N.

local function isDestinationLeftOrRight(origin: Vector3, originLook: Vector3, destination: Vector3): string
	
	-- let's make sure our originLook is a unit vector
	originLook = originLook.Unit
	
	local n =  Vector3.yAxis -- let's make it the y axis for this problem
	local m = (destination - origin).Unit
	local s = originLook:Cross(n).Unit
	
	local proj_l_m = m:Dot(originLook)
	local proj_s_m = m:Dot(s)
	
	local theta = math.atan2(-proj_s_m, proj_l_m)
	
	return (theta < 0 and "Right") or (theta > 0 and "Left") or "Straight"
end


print(isDestinationLeftOrRight(
	workspace.Origin.CFrame.Position,
	workspace.Origin.CFrame.LookVector,
	workspace.Destination.CFrame.Position
))

Here’s the test place:

left-or-right.rbxl (53.2 KB)

8 Likes

Are u using vectors to do this???

Have u learn about double angle formula

1 Like

Is this two-dimensional or three-dimensional?

1 Like

Thank you for your amazing response.

I will be marking this as the solution as it does exactly what I want to do. Your explanation is very interesting and I love the attention to detail.

2 Likes

This solution works, however, there’s a surprisingly easy way to do this without using trig.

The solution uses the assumption that the right vector of the origin is always going to point away from the left side, thus the dot product will always be negative on the left, and positive on the right. A dot product of 0 is perfectly perpendicular to the right vector, so the direction is straight:

local function getDirection(origin: CFrame, destination: Vector3)
    local travel = destination - origin
    local dot = origin.RightVector:Dot(travel)
    if dot < 0 then
        return "Left"
    elseif dot > 0 then
        return "Right"
    else
        return "Straight"
    end
end

Alternative compact function:

local function getDirection(origin: CFrame, destination: Vector3)
    local dot = origin.RightVector:Dot(destination - origin)
    return dot < 0 and "Left" or dot > 0 and "Right" or "Straight"
end

image

5 Likes

Nice! I didn’t even think about this approach, it’s a lot faster.

Now that I think about it, you could also look at the cross product of the look vector and the vector from origin to destination. Then check the sign of the Y component of the resulting vector.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.