Imagination PowerVR SDK Blog

Is that a bug in PVR vector math library?


Are you guys sure about the following code?

When multiplying a vector with a matrix using the following function my translation gets lost cause it is stored in 12,13,14

So to get the expected result I first have to take the transpose of my matrix or fix the following implementation as shown further below.

<br />
PVRTVec4& PVRTVec4::operator*=(const PVRTMat4& rhs)<br />
{<br />
VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2])+VERTTYPEMUL(w,rhs.f[3]);<br />
VERTTYPE ty = VERTTYPEMUL(x,rhs.f[4])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[6])+VERTTYPEMUL(w,rhs.f[7]);<br />
VERTTYPE tz = VERTTYPEMUL(x,rhs.f[8])+VERTTYPEMUL(y,rhs.f[9])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[11]);<br />
w = VERTTYPEMUL(x,rhs.f[12])+VERTTYPEMUL(y,rhs.f[13])+VERTTYPEMUL(z,rhs.f[14])+VERTTYPEMUL(w,rhs.f[15]);<br />
x = tx;<br />
y = ty;<br />
z = tz;<br />
return *this;<br />
}<br />

```<br />
<br />
Possible fix:<br />
<br />

PVRTVec4& PVRTVec4::operator*=(const PVRTMat4& rhs)
VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[4])+VERTTYPEMUL(z,rhs.f[8])+VERTTYPEMUL(w,rhs.f[12]);
VERTTYPE ty = VERTTYPEMUL(x,rhs.f[1])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[9])+VERTTYPEMUL(w,rhs.f[13]);
VERTTYPE tz = VERTTYPEMUL(x,rhs.f[2])+VERTTYPEMUL(y,rhs.f[6])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[14]);
w = VERTTYPEMUL(x,rhs.f[3])+VERTTYPEMUL(y,rhs.f[7])+VERTTYPEMUL(z,rhs.f[11])+VERTTYPEMUL(w,rhs.f[15]);
x = tx;
y = ty;
z = tz;
return *this;
<br />


Ok I think I figured it out.

I was doing vert*=mat which in fact is short for vert=vertmat

But what I really needed was vert=mat
vert which obviously works just fine.

Still that *= operator is a bit odd. Who actually needs that in OpenGL world?

Maybe it makes sense for DirectX though…


Hi Slion,

Actually they should behave as you described. In practice, the result of vertmat == matvert, as the results are the same. The reason for the incorrect calculation is because that calculation is somehow assuming a row-major matrix, when it should in fact be column major. This is a bug and we will fix it for the next release.




No wait, hang on, I just had to go write a lot of stuff on a whiteboard to figure this out. I was also looking at the wrong function. So the operator functions you mention ARE the correct way round. matvec is the correct way of performing a transformation in OpenGL, as you’ve discovered. The reason for having vecmat and vec*=mat is actually because it’s a shorthand (and more efficient) way of working out “I want to transpose this” without performing an actual transposition. This is useful for say, scaling matrixes, where the inverse == the transpose, so instead of doing “vec = mat / vec”, you can just do “vec = vec * mat” which is equivalent and cheaper to do.

We do have an incorrect function however, which is the really old “PVRTTransform” which despite having the vector as the first argument is actually doing “mat * vec”. We’ve no intention of fixing this though as it’s technically deprecated and we don’t want to break people’s codebases. A future SDK will remove this function and we’ll verify row vs column major maths in any new code from now on :slight_smile: