2

I have this equation with constant c and vec4 x=(x_1, x_2, x_3, x_4):

x_1*c + x_2*c + x_3*c + x_4*c

where sum(x_i) = 1

That means, the result should be c:

=(x_1 + x_2 + x_3 + x_4) * c

= 1 * c = c

So I have a vec4 and a matrix4*3 multiplication like this:

(x_1, x_2, x_3, x_4) * ((? c ?), (? c ?), (? c ?) (? c ?) )

However, the y coord in result (vec3) is not equal to c at all.

How is that and how to fix it?

float constant = 10.0f;
glm::vec3 v1 = glm::vec3(48.0f, constant, 18.0f);
glm::vec3 v2 = glm::vec3(56.0f, constant, 18.0f);
glm::vec3 v3 = glm::vec3(56.0f, constant, 12.0f);
glm::vec3 v4 = glm::vec3(52.0f, constant, 8.0f);
glm::mat4x3 M = glm::mat4x3(v1, v2, v3, v4);
glm::vec4 sumTo1 = glm::vec4(0.2f, 0.4f, 0.1f, 0.3f);
glm::vec3 result = sumTo1 * M;
cout << "sumTo1=" << glm::to_string(sumTo1) << endl;
cout << "M=" << glm::to_string(M) << endl;
cout << "result=" << glm::to_string(result) << endl;

Output:

sumTo1=vec4(0.200000, 0.400000, 0.100000, 0.300000)
M=mat4x3((48.000000, 10.000000, 18.000000), (56.000000, 10.000000, 18.000000), (56.000000, 10.000000, 12.000000), (52.000000, 10.000000, 8.000000))
result=vec3(15.400001, 17.000000, 16.400000)

To my knowledge the vector is considered as a row vector already.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Ecto
  • 1,125
  • 1
  • 7
  • 13

1 Answers1

4

OpenGL matrices and GLM matrices are stored in column major order. The vector has to be multiplied to the matrix from the right:

glm::vec3 result = sumTo1 * M;

glm::vec3 result = M * sumTo1;

See GLSL Programming/Vector and Matrix Operations
and OpenGL Shading Language 4.60 Specification - 5.10. Vector and Matrix Operations

The exceptions are matrix multiplied by vector, vector multiplied by matrix, and matrix multiplied by matrix. These do not operate component-wise, but rather perform the correct linear algebraic multiply.

vec3 v, u;
mat3 m;
u = v * m;

is equivalent to

u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);

And

u = m * v;

is equivalent to

u.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z;
u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z;
u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z;
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • doesn't it contradict this answer? https://stackoverflow.com/a/9863952/10976041 – Ecto May 22 '20 at 15:45
  • @Ecto Please respect the specification. I've extended the answer and add the specification of vector and matrix multiplications. – Rabbid76 May 22 '20 at 15:49
  • 2
    @Ecto "doesn't it contradict this answer?" no it doesn't. That answer gives explictely the example of `mat2x4*vec4` being invalid while `vec4*mat2x4` being valid. But what you attempt here is `vec4 * mat4x3`, which isn't valid, while `vec4*mat3x4` would be valid. – derhass May 22 '20 at 15:52
  • 1
    @Eco: glm can automatically transpose vectors. Which means that you can treat vectors either as row or as column vectors. But it doesn't transpose the matrix for you. vec4 * mat4x3 (vec4 as row-vector) is not a valid operation. mat4x3 * vec4 (vec4 as column-vector) is. – BDL May 22 '20 at 15:53
  • @BDL: "But it doesn't transpose the matrix for you." Even if it would do that, the transposed operation `mat3x4 * vec4` would be as invalid as the starting point `vec4 * mat4x3`. – derhass May 22 '20 at 15:56
  • @derhass: Correct. But `vec4 * mat3x4` would be the valid calculation op is looking for. What op actually calculates is `vec3 * mat4x3` (leaving away the z-component of the vector), then casting the resulting vec4 into a vec3. E.g.: `17 = 56*0,2+10*0,4+18*0,1` – BDL May 22 '20 at 15:57
  • exactly, the equation was actually more complicated (multiple matrixes) and because I didn't find an easy way to transpose glm::vec3 I just wrote it like that. – Ecto May 22 '20 at 15:59
  • @Ecto: You didn't write it like that. You wrote `vec4 * mat4x3` which is not the same as `vec4 * mat3x4`. – BDL May 22 '20 at 16:02
  • it was vec4 * mat4 * mat4x3. – Ecto May 22 '20 at 16:06
  • 1
    @Ecto: Doesn't matter. `mat4 * mat4x3` is still not a valid matrix multiplicaton. The number of rows of the first matrix has to match the number of rows of the second. #columns(mat4) = 4, #rows(mat4x3) = 3. No match -> no valid multiplication. Are you confused because the traditional mathematical form is `rows x columns` but glsl uses `columns x rows`? – BDL May 22 '20 at 16:09