recp / cglm

📽 Highly Optimized 2D / 3D Graphics Math (glm) for C
MIT License
2.33k stars 231 forks source link

Proposal: optimized functions to multiply 3 matrices at once without using _mulN #124

Open recp opened 4 years ago

recp commented 4 years ago

It is common to multiply Model, View and Project matrices together, there may be additional matrices to multiply...

We have two option to multiply 3 matrices:

  1. Using glm_mat4_mulN() which is nice helper but it uses loop.
  2. Using two glm_mat4_mul() call which is general.

Proposal:

New functions to multiply 3 or 4 matrices.

same for mat2 and mat3. Better names and ideas are always welcome. These functions will be optimized especially with SIMD, loop will not be used.

This will also make engines, renderers, games... faster and with less cglm call[s] and more readable, more neat... 🤗

Lambdara commented 4 years ago

mvp vs pvm?

I would suggest pvm, for Proj * View * Model; as you would usually translate a vertex by going Proj * View * Model * vertex, if I'm not mistaken. I guess the full name would best be glm_mat4_pvm or glm_pvm; I don't think mul really adds anything (is there any other kind of functionality involving these three that you would expect there to be?)

acoto87 commented 4 years ago

I like the glm_mat4_mul3x and glm_mat4_mul4x variants, as you could use these functions for other stuff other than multiplying Model * View * Proj.

recp commented 4 years ago

@Uwila , @acoto87 thanks for reviewing this proposal!

if I'm not mistaken. I guess the full name would best be glm_mat4_pvm or glm_pvm;

glm_pvm(projection, view, model, dest) or glm_mvp(model, view, projection, dest) are the name candidates, not glm_mat4_pvm...

the multiplication order will same: ### Projection View Model for both glm_pvm() and glm_mvp().

single call will make things more readable and faster because, I want to optimize triple matrix multiplication in one function to get maximum performance and less instructions and less binary size.

I don't think mul really adds anything (is there any other kind of functionality involving these three that you would expect there to be?)

I guess you are talking about glm_mat4_mul3x() and glm_mat4_mul4x() ... these will be general matrix multiplication. _pvm() version is optimized for affine transforms.

For instance there are a few functions to multiply mat4 in cglm:

  1. glm_mat4_mul() - optimized, general purpose matrix multiplication.
  2. glm_mul() - optimized for affine transforms; the last element of rotation part must be zero like:
/* affine-mat.h */

R  R  R  X
R  R  R  Y
R  R  R  Z
0  0  0  W
  1. glm_mul_rot() - optimized for rotation transforms:
/* affine-mat.h */

R  R  R  0
R  R  R  0
R  R  R  0
0  0  0  1
Lambdara commented 4 years ago

I guess you are talking about glm_mat4_mul3x() and glm_mat4_mul4x() ... these will be general matrix multiplication. _pvm() version is optimized for affine transforms.

I meant in the context of _pvm; you listed glm_mvp(m, v, p), glm_pvm(p, v, m), glm_mul_mvp(m, v, p) and glm_mul_pvm(p, v, m) as candidates; not that it matters much but I meant to say that mul doesn't really add anything in this case.

acoto87 commented 4 years ago

I kind of agree with @Uwila but with the names glm_mvp or glm_pvm it's lost in the name of the function what does the function do. It's general knowledge that what you do with those matrices are multiplying to together to get the final transformation matrix. If that is the case, those names are fine, if it could be cause of confusion I would prefer the explicit glm_mul_mvp and glm_mul_pvm.

About the order of the parameters, it's a matter of semantics when you talk about it;_pvm indicates exactly the order in which the matrices will be multiplied: Proj * View * Model so there is no ambiguity there, and the _mvp indicates generally the operation that you are doing (without explicitly telling the order of the multiplication and I think it's the most common way people refers to this operation), in like: "I'm just calculating the final transformation with matrices Model, View, Proj.

That last version could also create confusion, because you can treat that operation as:

depending on how you store matrices, but since this library store matrices column-wise, the latter is what will be used, and the explicit _pvm makes more sense.