One Normal From Two Normals ?

Started by
9 comments, last by oliii 16 years, 10 months ago
Hi guys, I'm working in 2D and want to create a normal that's a combination of two other normals. A good example is a corner with the two normals at right angles to each other, like this: norm_1=(0,1) norm_2=(1,0) un-normalized corner=(0.5,0.5) Do I just linearly interpolate with 0.5 ? I basically have two line segments that meet at a common vertex and I want the normal of that vertex. I know a point technically doesn't have a normal but I need it for collision response so I thought a good way would be to use the 'average' of the line segment normals. Thanks.
Advertisement
I think that should be fine. Does your collision response work correctly using that method? If so, then it's fine. If not, we might need to know a bit more about what's going on.
Assuming that you want a normalised normal from two normalised normals (am I seeing double?), then a equally weighted lerp won't do the trick. An equally weight slerp will, but there's no need to go around the houses.

The simple answer is to add the two normals, then normalise the result. The new vector will point in the same direction as in your 0.5-lerp approach, but is also guaranteed to have unit length. This will fail if the two source normals are anti-parallel, but it's very tricky to define a good answer in that case anyway.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Vector2D P,Q; // normalized 2D vectorsdouble A = abs(atan2(P.y, P.x) - atan2(Q.y, Q.x));Vector2D R = (sin(A*0.5)*P+sin(A*0.5)*Q)/sin(A);

Quote:Original post by pTymN
Vector2D P,Q; // normalized 2D vectorsdouble A = abs(atan2(P.y, P.x) - atan2(Q.y, Q.x));Vector2D R = (sin(A*0.5)*P+sin(A*0.5)*Q)/sin(A);
After factoring, this is the same as saying R = (P + Q) * K, in which case you might as well just write R = Normalize(P + Q).



Surely

R = (P+Q)/2

is faster to avoid the normalisation?
Quote:Original post by esuvs
Surely

R = (P+Q)/2

is faster to avoid the normalisation?


Um, but the OP wants a normalized vector and what you're proposing doesn't ensure that.

--www.physicaluncertainty.com
--linkedin
--irc.freenode.net#gdnet

Quote:Original post by pTymN
Vector2D P,Q; // normalized 2D vectorsdouble A = abs(atan2(P.y, P.x) - atan2(Q.y, Q.x));Vector2D R = (sin(A*0.5)*P+sin(A*0.5)*Q)/sin(A);

Hey, I didn't realise we were going for the over-complication award! Here's my entry (There's $1,000,000 up for grabs if you can prove it works [wink])

Vector3 AverageNormal(Vector2 P, Vector2 Q) {    Polynomial zeta = Polynomial::Parse("sum[1/n^s, n=1..infinity]", "s");    Complex root = zeta.FindRoot();    while (!((root / -2).IsNatural())) {       zeta = zeta / Polynomial::Parse("s - {c1}", "s", root);    }    Real one_half = Complex::RealPart(zeta.Evaluate(root));       Vector2P P_polar = Vector2P::FromCartesian(P);    Vector2P Q_polar = Vector2P::FromCartesian(Q);    Real difference = LogNatural(Exp(P_polar.Arg()) / Exp(Q_polar.Arg()));    Integer even_int = Integer::Random(0, Integer::infinity) * 2;    Real abs_difference = Power(Power(difference, even_int.ToReal()), even_int.Reciprocal());    Real half_angle = Dot(one_half.ToVector1, abs_difference.ToVector1).X;    Complex i = Complex::FromImaginary(1);    Real weight_half = Complex::ImaginaryPart(Sinh(i * half_angle));    Real weight_total = Power(1 - Power(Cos(abs_difference), one_half.Reciprocal()), one_half);    Vector2 R1 = (P.CyclicPermute(1).ScalarMultiply(weight_half)).CyclicPermute(-1);    Vector2 R2 = (Q.CyclicPermute(-1).ScalarMultiply(weight_half)).CyclicPermute(1);    Vector2 R_scaled;    R_scaled.y = R2.x + R1.x;    R_scaled.x = -R1.y - (R2.y).Negate();    R_scaled.CyclicPermute(even_int - 7);    Vector2 R = R_scaled.ScalarDivide(weight_total);    Complex::Function f = Complex::Function::Parse("z - z^14", "z");    String sie = "1/(2 * pi * i) int[f(t) / t - z, t]";    Complex::Function g = Complex::Function::Parse(sie, "z");    Complex z = Complex::Random();    return R.ScalarMultiply(f(z) / g(z));}


Okay, so I'm just teasing. But your function seems a little over-the-top, considering the alternatives. I don't think it gets much cleaner than this:

Vector2D P,Q; // Any 2D vectorsVector2D R = P + Q;R.Normalise();

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
R = (P+Q) * 0.707107

:p
I guess that all of our methods fail if P and Q are opposing...

This topic is closed to new replies.

Advertisement