Notifications
Clear all

[Closed] BlendMatrix

Here is what I use for simple (closest) matrix blending (c++)

Matrix3 BlendMatrix(Matrix3 tm0, Matrix3 tm1, float param)
{
	AffineParts p0;
	decomp_affine(tm0, &p0);

	AffineParts p1;
	decomp_affine(tm1, &p1);

	Point3 pos = p0.t * (1-param) + p1.t * param;
	Point3 scl = p0.k * (1-param) + p1.k * param;

	p1.q.MakeClosest(p0.q);
	Quat rot = Slerp(p0.q, p1.q, param);

	Matrix3 tm;
	rot.MakeMatrix(tm);
	tm.PreScale(scl);
	tm.Translate(pos);

	return tm;
}

it’s almost the same as your code above

though modern compilers are usually very good on returning larger objects, I’d still go with this…

void BlendMatrix(const Matrix3& tm0, const Matrix3& tm1, float param, Matrix3& tm)

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

I also use this version …

The return version I usually use in animation methods, and the instance passing version I use for deformations.

I did a little research too and found that for modern compilers there is not much difference in both ways (11+). I choose one against the other to make it easier to work with my data.

 MZ1

Thank you @denisT , This is C# version:

private readonly static IGlobal globalInterface = GlobalInterface.Instance;
IMatrix3 BlendMatrix(IMatrix3 tm0, IMatrix3 tm1, float param)
{
    IAffineParts p0 = globalInterface.AffineParts.Create();
    globalInterface.DecompAffine(tm0, p0);

    IAffineParts p1 = globalInterface.AffineParts.Create();
    globalInterface.DecompAffine(tm1, p1);

    IPoint3 pos = p0.T.MultiplyBy(1 - param).Add(p1.T.MultiplyBy(param));
    IPoint3 scl = p0.K.MultiplyBy(1 - param).Add(p1.K.MultiplyBy(param));

    p1.Q.MakeClosest(p0.Q);
    IQuat rot = globalInterface.Slerp(p0.Q, p1.Q, param);

    IMatrix3 tm = globalInterface.Matrix3.Create(true);
    rot.MakeMatrix(tm,false);
    tm.PreScale(scl);
    tm.Translate(pos);

    return tm;
}

This blend function works, but I have new problem which happen randomly when I blend from 0 to 1:
It will return infinity values (NAN) in some cases, I’m not sure from which part of my code this is coming, Maybe there is some memory leak as @Serejah mentioned. but are you sure this method works for all transformation data? for all cases?

try re-inserting the early bail checks

 MZ1

The problem came from other part of my code. now is working correctly. Thanks!
(used MultiplyBy instead of Multiply)

 MZ1

Your code use second method of interpolation which is more correct, right? from wiki

// Imprecise method, which does not guarantee v = v1 when t = 1, due to floating-point arithmetic error. This method is monotonic
// This form may be used when the hardware has a native fused multiply-add instruction.
float lerp(float v0, float v1, float t) {
return v0 + t * (v1 – v0);
}

// Precise method, which guarantees v = v1 when t = 1. This method is monotonic only when v0 * v1 < 0. Lerping between same values might not produce the same value
float lerp(float v0, float v1, float t) {
return (1 – t) * v0 + t * v1;
}

they are algebraically identical

a + t(b-a)
a + tb – ta
a – ta + tb
(1-t)a + tb

see the code above…

Matrix3 BlendMatrix(Matrix3 tm0, Matrix3 tm1, float param) { ... }

This doesn’t work for non-orthogonal matrices … Any ideas how to blend non-orthogonal ones?

I found solution.
In case of non-orthogonal matrix we have to take into account “stretch” rotation quaternion as well. It needs to be blended the same way as “essential” rotation using Slerp.
Because we have to use “stretch” rotation the blended Matrix should be composed using compose method for Affine parts.

Page 2 / 2