Matrix calculation issue

I just recently got into matrix calculation, so might be that i got the whole system sorta wrong, but lets try. I want to create a transformation matrix which includes a translation and a scale. I start with an identity Matrix and then apply these transformations one after the other. Do i have to use “scaleMat” or “setScaleMat” for the scale then? Maybe i have a wrong understanding of these commands, but both pretty much overwrite the matrix with a new matrix which implements only the scale:

>>> myMatrix=Mat4()
>>> myMatrix
Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
>>> myMatrix.setTranslateMat(Vec3(2.0,3.0,4.0))
>>> myMatrix
Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 3, 4, 1)
>>> myMatrix.setScaleMat(Vec3(2.0,2.0,2.0))
>>> myMatrix
Mat4(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)

…does pretty much the same as…

>>> myMatrix=Mat4()
>>> myMatrix
Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
>>> myMatrix.translateMat(Vec3(2.0,3.0,4.0))
Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 3, 4, 1)
>>> myMatrix.scaleMat(Vec3(2.0,2.0,2.0))
Mat4(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)

In both variations the translation gets overwritten by the scale… At the moment i am implementing it by creating two seperate matrices and multiplying them into one. It works, but it feels like a workaround for an issue, or am i wrong? I mean, why are there two different commands, that always come up with the same result?

Just as reference, i checked it back with CGKit’s way and there the calculation turnes out like i expected it:

>>> myMatrix=mat4(1.0)
>>> myMatrix.translate(vec3(2.0,3.0,4.0))
[1, 0, 0, 2]
[0, 1, 0, 3]
[0, 0, 1, 4]
[0, 0, 0, 1]
>>> myMatrix.scale(vec3(2.0,2.0,2.0))
[2, 0, 0, 2]
[0, 2, 0, 3]
[0, 0, 2, 4]
[0, 0, 0, 1]

Here the translation part is still there. Is this valid?

you will find lot of equal commands when you use different libaries.
if you dont trust a operation, then you have to code them by yourself.

matrices math example (linuxtopia.org):

m1 = [ [1, 2, 3, 0], [4, 5, 6, 0], [7, 8, 9, 0] ]
m2 = [ [2, 4, 6, 0], [1, 3, 5, 0], [0, -1, -2, 0] ]
m3= [ 4*[0] for i in range(3) ]

for i in range(3):
    for j in range(4):
        m3[i][j]= m1[i][j]+m2[i][j]

this side was helping me:
linuxtopia.org/online_books/ … 20s05.html

It probably doesn’t need to be said, but in case this thread comes up in a search on the subject, there aren’t may cases in Panda in which you’ll need to use matrices- certainly not simple translation/rotation/scale of nodes in the average use case. It’s much simpler to just use the setPos/setHpr/setScale NodePath methods.

As to your particular case, yeah, it sounds like whatever call you’re using is replacing the existing transform with the newly generated one, rather than multiplying implicitly. I’ve only ever needed to poke at the actual matrices once or twice, so I couldn’t tell you offhand what command sets will be useful if the manual isn’t helping. Iirc, though, there are ways to get the transformation matrix of a NodePath, so one alternate route might be do whatever you want to a dummy node, then get the composited transform directly from it. This will neatly sidestep multiplication-order confusions that nearly always happen when you try to composite matrices by hand.

My guess is the setXXXMat methods are building those matrices from an identity. You could just concat separate matrices for whatever collective transform you want?

in his case for sure :wink: is he writing/ transforming verteces :smiley:

there lot of reason where you need multidimensional arrays, at my game i needed it, but not vertex data related.

Exactly right. Panda’s setTranslateMat() is not the same method as CGKit’s translate(). The former method is designed to completely replace the matrix with one that implements a translation, the latter is designed to compose the matrix with an implicit translation matrix.

The correct way to use these methods in Panda is to construct the matrices individually and multiply them together.

But also as said above, you almost never really need to do this. Panda has much higher-level functions for dealing with transforms that take all of this nonsense out of your hands.

David

what hard words.
it makes sense to know how to handle matrices :wink:

anyway, which workaround would you use to rotate clusters in clusters? would you parent your pieces onto a dummyNode? !

what is the incorrect way? if you have no other chance to structure a array, like to cut them in pieces? is there a other way too?

here a example for rotating,scale and translate a geometry…

'''
Created on 06.08.2009

@author: dirk hochegger
'''
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.directtools.DirectGeometry import LineNodePath 
from pandac.PandaModules import Vec4
import math
class MATRICES(DirectObject):
    '''
    classdocs
    '''
    def __init__(self):
        '''
        Constructor
        '''
        self.light1 = LineNodePath(render2d,'light',2,Vec4(1,1,.2,.2))
        taskMgr.add(self.rotate,"rot")
    def draw(self):
        self.light1.remove()
        self.light1 = LineNodePath(render2d,'light',2,Vec4(1,1,.2,.2))
        self.light1.drawLines(self.matrix)
        self.light1.create()
    def rotate(self,task):
        rot = task.time
        length = .5*math.sin(rot)        
        self.matrix = [[(length*math.cos(rot)+math.cos(rot/4)/2,0,length*math.sin(rot)+math.sin(rot/4)/2),(-length*math.sin(rot)+math.cos(rot/4)/2,0,length*math.cos(rot)+math.sin(rot/4)/2)],
                 [(-length*math.sin(rot)+math.cos(rot/4)/2,0,length*math.cos(rot)+math.sin(rot/4)/2),(-length*math.cos(rot)+math.cos(rot/4)/2,0,-length*math.sin(rot)+math.sin(rot/4)/2)],
                 [(-length*math.cos(rot)+math.cos(rot/4)/2,0,-length*math.sin(rot)+math.sin(rot/4)/2),(length*math.sin(rot)+math.cos(rot/4)/2,0,-length*math.cos(rot)+math.sin(rot/4)/2)],
                 [(length*math.sin(rot)+math.cos(rot/4)/2,0,-length*math.cos(rot)+math.sin(rot/4)/2),(length*math.cos(rot)+math.cos(rot/4)/2,0,length*math.sin(rot)+math.sin(rot/4)/2)]]   
        self.draw()
        return task.cont
m=MATRICES()      
run()

I understand that, but what’s the difference between Panda’s “setScaleMat()” and “scaleMat()”? In my example they both create the same results and the latter implies that it would scale the matrix when it actually replaces it…

True, panda does a great job there, no question. Just my tree script works a lot easier with matrices, therefore i use them… I pretty much was just intrigued and thought it’s a little odd to have two functions doing the same thing…

I believe that scaleMat is a static function which returns a matrix that performs the indicated scale.

The method setScaleMat, on the other hand, fills in an already existing matrix.

So basically, this:

yourMatrix = Mat4()
yourMatrix.setScaleMat(yadda)

Is the same as:

yourMatrix = Mat4.scaleMat(yadda)

The function scaleMat is basically a static shorthand version that can quickly be used in a multiplication operation (or so) without having to create a new matrix, etc.

I bet you are confused by the fact that, even though scaleMat is a static function, it can be called on a particular instance of a matrix as well, even though that doesn’t make much sense.

Thanks for the clarification! Yup, i suspected something like that. I just wanted to be sure before i code something like this… :wink:

myMatrix=myMatrix*myMatrix.scaleMat(myVector) # myMatrix scale