# Calculating Right Vector from Two Points

This topic is 1330 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Original Thread from Unreal Engine Forums

Hello all! I am working on a water/river mode plugin for the Unreal Engine 4.  It seems to be coming along alright.  I have the base features working except for one partially works.  And that one is moving a spline to adjust the path.

The problem is that as I extend move it more to the right or left, it gets weird:

I already know what the problem is:

FVector extendDir = FVector(0, width, 0);

one.Vertex0.Position = v0;
one.Vertex1.Position = v0 + extendDir;
one.Vertex2.Position = v2;

two.Vertex0.Position = one.Vertex2.Position + extendDir;
two.Vertex1.Position = one.Vertex2.Position;
two.Vertex2.Position = one.Vertex1.Position;


It is because I'm extending it on the Y-axis. I did it intentionally for testing purposes. Now that I know that the mesh renders alright, the next thing on my list is to get the right vector of a segment on the spline component so I can extend the mesh in that direction. That way, it will never get squished like that and the width of the mesh will stay constant throughout the whole thing. How would I do this? Is it possible? I've been trying to do this all day. And I cannot use the point's rotation because it has not been rotated, I just moved it. Is there a way to calculate this using the first point and connected point or something? Thanks!

##### Share on other sites

I'm not sure what your problem exactly is. So I describe the entire process in a more or less coarse manner, and we can go into details at the step identified by you.

1.) Sub-divide the spline path into linear segments.

2.) Compute the (perpendicular) sideway vectors at the beginning and end of each segment.

3.) Compute a common vector for each pair of sideway vectors from the end of one segment and the beginning of the next segment. This step is used to avoid a gap on an outside bend or an overlapping on an inside bend, resp.

4.) Compute a sideway displacement of the line segment using a defined (half) width, so that a closed mesh is yielded in.

##### Share on other sites

I'm not sure what your problem exactly is. So I describe the entire process in a more or less coarse manner, and we can go into details at the step identified by you.

1.) Sub-divide the spline path into linear segments.

2.) Compute the (perpendicular) sideway vectors at the beginning and end of each segment.

3.) Compute a common vector for each pair of sideway vectors from the end of one segment and the beginning of the next segment. This step is used to avoid a gap on an outside bend or an overlapping on an inside bend, resp.

4.) Compute a sideway displacement of the line segment using a defined (half) width, so that a closed mesh is yielded in.

What I am trying to do is get away from this:

FVector extendDir = FVector(0, width, 0);


Because it always extends the mesh on the Y axis, I get this result if I move the spline back while moving it left or right:

What I would like to do is have the mesh maintain it's width where ever it is.  I don't want it to get squished together, it needs to be the same width at the end as it was before.  So I would like to have everything extend according to the right vector's of the points.

1) I have everything sub-divided and I can change how may segments each part is sub-divided into:

2) I've calculated the sideway vectors for each segement (bottom left point of triangle to left top point of triangle).  Does this look correct?

// Transform the bottom left point of the triangle and left top point of the triangle by y axis to get the right vector.
FVector v0right = FRotationMatrix(Path->GetWorldRotationAtDistanceAlongSpline(Path->GetDistanceAlongSplineAtSplinePoint(i) + (segmentLength * s))).TransformVector(FVector(0, 1, 0)).SafeNormal().ForwardVector;
FVector v2right = FRotationMatrix(Path->GetWorldRotationAtDistanceAlongSpline(Path->GetDistanceAlongSplineAtSplinePoint(i) + (segmentLength * s) + segmentLength)).TransformVector(FVector(0, 1, 0)).SafeNormal().ForwardVector;


3) How would I compute the common vector?

4) How would I compute a sideway displacement?

Thanks!

Edited by KamRandle

##### Share on other sites

Let the spline be divided in segments, so that a sequence of positions

{ p0, p1, p2, ... , pn }

is given. The difference vector

di := pi - pi-1, 0 < i <= n

"ties" 2 consecutive points. Its projection onto the ground plane (assuming this is the x-y plane) is

d'i := ( di;x, di;y, 0 )

and the belonging sideway vector, i.e. one of its both perpendicular vectors in the plane, normalized, is

si := ( di;y, -di;x, 0 ) / | d'i |

This could be used to calculate the 4 corner points of a quad with width w for the segment i as

pi-1, pi, pi + si * w, pi-1 + si * w

Although each segment gets the same width w, the result looks bad because of the said gaps and overlaps. This is because at any intermediate pi there are 2 sideway vectors si and si+1, and they are normally not identical.

Now, a better crossing point would be located somewhere on the halfway vector

hi := si + si+1

which is in general no longer perpendicular to one of the both neighboring segments, so that it cannot be simply scaled like

hi / | hi | * w

in order to yield in a constant width of the mesh.

Instead, using a scaling like so

vi := hi * w / ( 1 + si . si+1 )

does the trick (if I've done it correctly). It computes to a vector with exemplary lengths

| vi | = w

| vi |90° = 1.414 w

| vi |-9 = 1.414 w

| vi |45° = 1,08 w

what seems me okay.

Then the quad for segment 0 has the corners

p0p1p1 + v1p0 + s1 * w

and intermediate segment's quad has the corners

pi-1pipi + vipi-1 + vi-1

and the quad for segment n has the corners

pn-1pnpn + sn * w, pn-1 + vn-1

However, I'd consider to use the spline as middle of the river instead of an edge.
Edited by haegarr

##### Share on other sites

Hey haegarr! Thanks for the help so far, I really appreciate it.  Sorry to bug you with all these questions, but I found a way to get the right vector using the points rotation (I didn't know it had a function like that until yesterday) and was wondering if this looks right now:

float distance = Path->GetDistanceAlongSplineAtSplinePoint(i) + (segmentLength * s);
float distance2 = Path->GetDistanceAlongSplineAtSplinePoint(i) + (segmentLength * s) + segmentLength;

FVector v0 = GetTransform().InverseTransformPosition(Path->GetWorldLocationAtDistanceAlongSpline(distance));
FVector v2 = GetTransform().InverseTransformPosition(Path->GetWorldLocationAtDistanceAlongSpline(distance2));

FRotator v0Rotation = Path->GetWorldRotationAtDistanceAlongSpline(distance);
FRotator v2Rotation = Path->GetWorldRotationAtDistanceAlongSpline(distance2);

FVector s1 = FRotationMatrix(v0Rotation).GetScaledAxis(EAxis::Y);
FVector s2 = FRotationMatrix(v2Rotation).GetScaledAxis(EAxis::Y);

FVector h = s1 + s2;

FVector extendDir = h * width / (FVector(1, 1, 1) + s1 * s2);


I was a little confused about calculating vthough (extendDir is that vector).  How I read it was "[halfway vector] multiplied by [width] divided by [a vector with all components set to 1] plus [sideway vector 1] multiplied [sideway vector 2]".  I'm pretty sure I didn't read it right.  Can you type the equation out in words? lol And are these the right points for each calculation?

Thanks for the help, I really appreciate it again man!

Edited by KamRandle

##### Share on other sites

Hey! I got some sleep and I understand it now.  Lol I don't know why I was thinking it was a multiplication sign.  I changed it to "1 + FVector::DotProduct(s1, s2)" now. :D I will be testing it soon.

##### Share on other sites

Hey haegarr! I got it working thanks to you! Thanks! :D

Edited by KamRandle

• 37
• 12
• 10
• 10
• 9
• ### Forum Statistics

• Total Topics
631362
• Total Posts
2999562
×