Benjamin Frémiot
2008-05-19
Hi,
I have 1 question about scaling in the mat4 Matrix class.
In fact, I'm developing a 3d software using the 3d rendering engine panda3d (http://www.panda3d.org). Panda has its own Matrix class for the models and node of the scenegraph.
The thing is that, with Panda, when you ask for the scaling of one node (so of one matrix), it gives you the scale of the axes of the node.
So if you said :
node.setScale(10,15,20)
You can then translate/rotate this node and translate/rotate/scale its ancestor (as the scenegraph is a matrix tree), and then ask again for the node's scale and it will give you :
(10,15,20)
The thing is that cgkit's mat4s don't seem to have this behavior. I made different tests scaling and rotating mat4s and I concluded that the mat4.scale(x,y,z) scale the matrix's
axes in the world scene.
My problem with this system is that I have lot's of nodes in my tree; so, to get the local axis' scale, I have to do lots of multiplications and inversions.
Is there any way to have the same scale setting behavior that Panda3D's Mat4 with cgkit's mat4?
Thanks.
Benjamin FREMIOT
PS : Here's one of my small tests
from math import pi
import cgkit
# ==
m = cgkit.cgtypes.mat4(1)
m.rotate(pi/2, (0,0,1))
m.scale((2,3,4))
m.rotate(-pi/2, (0,0,1))
m.decompose()
((0, 0, 0),
[ 1, 2.04101e-17, 0, 0]
[-2.04101e-17, 1, 0, 0]
[ 0, 0, 1, 0]
[ 0, 0, 0, 1],
(3, 2, 4))
# I was waiting for scale == (2,3,4) as I thought it was a setScale operation
# So a final matrix looking like that :
[2, 0, 0, 0]
[0, 3, 0, 0]
[0, 0, 4, 0]
[0, 0, 0, 1]
Matthias Baas
2008-05-21
Well, the decompose() method basically just calculates three matrices that can be multiplied in a particular order to get the original matrix. And because the matrix is really just stored as 16 values it doesn't know how a particular matrix was constructed in the first place. In your example code you are doing two rotations but the final matrix won't know this anymore. Each rotate, scale or translate operation is really just a shorthand for creating a particular matrix and multiplying this matrix with the current matrix.
Now if you want to store a transformation that is composed of a translate, scale and rotatation part (in a predefined order that differs from what decompose() is assuming) then I would really recommend to store those parts individually (this is what is done with the WorldObjects in cgkit). This has the advantage that you can easily change the values and that they also remain stable, whereas if you only store the resulting matrix your actual scale values may drift away from their initial values if you do, say, a lot of tiny rotations.
I hope this helps somewhat.
- Matthias -
Benjamin Frémiot
2008-05-22
Thanks a lot for your message!
I have no problem understanding the matrices and their behavior with transformations composition. Still I haven't succeeded in coding the behavior I'm talking about.
But with WorldObjects, you saved my day/week/life :-D
In fact a few months ago, I created a class that does exactly the same things that WorldObject (TreeNode + Matrix + pos/hpr accessors to matrix), except for the scale given in the matrix and the compute speed that is, on some points, better with WorldObjects.
So thanks again, it really helps ;-)
Benjamin