Slerp over a triangle?

Started by
8 comments, last by Ryokeen 8 years, 9 months ago

Hello.

I have a rather interesting problem. I have a triangle with 3 corners, each holding a a unit vector (say a normal). I also have two alpha values, a0 and a1. Together, I calculate a point on the triangle like this:


result = v0 + (v2 - v0) * a0 + (v1 - v0) * a1
result.normalize()

Although this correctly produces a new unit vector, the result is skewered by the linear interpolation. What I actually want to do is spherical linear interpolation (slerp) between these 3 vectors based on a0 and a1, but I have no idea how to slerp between more than 2 vectors. I can't really find any information on it either. This is to be done at load time once, so performance is not much of an issue here.

Advertisement

What is context of problem? What you are really trying to achieve?


Although this correctly produces a new unit vector, the result is skewered by the linear interpolation. [...]

This does not make sense. You are computing a position vector, and normalizing such a vector gives you nothing but the direction from the origin towards that position. That is probably not what you want to do. So, as kalle_h already requested: What do you want to achieve?

If you want to get the normal of the triangle at the position given by (a0,a1), then you need to interpolate normal vectors, not position vectors. Do you have the normals for the vertices at the positions of v0, v1, v2?

Okay, I'll try to explain it a bit better.

The triangle is part of the surface of a sphere with radius 1. That means that the position and the normal of the vertices are both identical, but in this case it does not matter what the positions of the vertices are. I already have the alpha values a0 and a1, which do not define a position.

result = v0 + (v2 - v0) * a0 + (v1 - v0) * a1

- If a0 = 0 and a1 = 0, then the result is v0

- if a0 = 1 and a1 = 0, then the result is v2

- if a0 = 0 and a1 = 1, then the result is v1

- a0 + a1 are always <= 1, as otherwise the point lies outside the triangle.

The problem with this is that it walks along the surface of the triangle, which actually represents the surface of a sphere. I want it to walk in an arc over the sphere (slerp). I basically want to interpolate a unit length normal over a triangle without distorting it on the CPU, which means using slerp instead of lerp.

Once you have the new normal (the result of your current calculation), multiply it by the sphere radius and add that to the sphere’s center point. If that isn’t the result you want (you want to change how to interpolate) then I would simply replace the vector math with quaternion math (and then use the above to get the new point on the sphere).


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

If you're about to interpolate between normals of a triangle, you might interpolate from v0 to v1 and the from that result to v2(T-shaped interpolation in a triangle)

so you would need something like:

vtemp = v0+(v1-v0)*a0;

result = vtemp + (v2-vtemp)*a1;

that gives different results that what you might want, but in case of a0 = 0.5 , a1 = 0.5 your code would give a vector halfway between v2,v0 and v0,v1

Could be that i don't make sense :D

Or you need 3 alpha values and go with

https://en.wikipedia.org/wiki/Barycentric_coordinate_system

I figured it out!

WDc4lWH.png

Given the normals of corners V0, V1 and V2, and the alpha values a0 and a1 that are to be used as in the picture (the picture uses the example values (0.5, 0.5)), I want to use spherical linear interpolation to calculate the normal.

I realized that this can be done using 3 slerps. First I slerp based on a0 between v0 and v2 AND between v1 and v2. The normal we're looking for lies inbetween these two resulting normals, so we slerp again between those two based on (a1 / (1.0 - a0)).


slerp0 = v0.slerp(v2, a0);
slerp1 = v1.slerp(v2, a0);

result = slerp0.slerp(slerp1, a1 / (1.0-a0));

Sadly it didn't help much in my case, but someone might find it useful.

I think L. Spiro's suggest should lead to the undistorted sphere you want.

otherwise, describe the problem in more detail and why your slerps don't help. I'm sure we'll find a solution together.

slerp0 = v0.slerp(v2, a0);
slerp1 = v1.slerp(v2, a0);

result = slerp0.slerp(slerp1, a1 / (1.0-a0));

a1 / (1.0-a0) will be greater than 1 if a0 > 1.0-a1 I think?

o3o

I assume that a0 = 0.5 , a1 = 0.5 should give you the average normal of all 3 corner normals right ?

If so the 3 slerps won't work as you get (0.5 / (1.0-0.5)) as the last slerp param wich would just give you a normal halfway between v1 and v2 not v0,v1,v2

Also you could get 0/0 for a1 = 0.0 , a0 = 1.0

And just a small question : Why do you try to do that with just 2 alpha values ?

Or another idea : "intersect" a ray from v1 to the point(p) you want to calculate the normal(N) for with the line/plane segment of (v0,v2) and use the resulting percentage of distance from intersection point(Ip) to v0 as a0 and from lp to p as a1.

Then :


slerp0 = v0.slerp(v2, a0);
result = slerp0.slerp(v1, a1);

Still satisfies a0 and a1 in range of 0..1 -> inside triangle

This topic is closed to new replies.

Advertisement