rotation + translation in a matrix 4x4

yesterday i open a similar TD.

now the issue , is the rotation with a translation(position)

how make a rotation on a global axis without changing the position (translation) ?

this is the script “WIP” …
this WORK , but maybe need to a cleanup ? or is right ?

(m4 is a matrices 4x4 that i want change)

        from mathutils import Matrix

        oldPosition = m4.translation                       #store the position before the transformation
        m4 = Matrix().Rotation(0.1, 4, "Z") * m4      #make the rotation
        m4.translation = oldPosition                       #replace the old position

i tried to make this before :
m4 = Matrix().Rotation(0.1, 4, “Z”) * m4

but this change also the position, while i not want change the position , but only the orientation…

The transformation from local space two worldspace can be expressed as matrix.

This transformation matrix van be generated by a sequence of basic transformations (rotation, translation, scale, shear, etc.). The order of this transformations is important.

E.g. you get a different transformation when you rotate and translate rather than translate and scale with the same parameters.
When looking at matrix multiplication the left multiplications are computed first. So you read the operations from left to right.

T = RotX * TranslZ * RotZ

you can indeed move an object to a new location and move it back.
E.g. the object is at (0,0,10) and you want to rotate it around its center.

Then you do: Translation(0,0,-10) * Rotate * Translation(0,0,10)

Knowing this shows you operations in worldspace are left multiplied and operations in local space are right multiplied.

T = Tglobal * T * Tlocal

I hope this is somehow correct and understandable.

Btw. you need 4x3 to project translation in 3D space. A 3x3 will not do that (it can project rotation and scale only). Usually the 4x3 is completed to a 4x4 to make it symetrical. This makes it easier to deal with.

i not found a way to rotate a 4x4 ,lack ever some piece, since:
or I remake it from scratch all (rotation,position,scale individually,but this required a lot of line)
or (more simple) i overwrite the translation .(but also this require some bad line)

what seem to me a bug is that you cannot use “rotate()” with a 4x4

m4.rotate(otherRotation) #error

maybe with 4x3 work? how make 4x3 ?

basically my goal is replace this line

own.applyRotation((0, 0, 0.1), 0) 

with this :

own.worldTransform = ?

You have just done ​​the matrix multiplication in the wrong order.

m4 = own.worldTransform
own.worldTransform = m4 * Matrix().Rotation(0.1, 4, "Z") 

Here a full example.

import bge
import mathutils
import math

cont = bge.logic.getCurrentController()
own = cont.owner

mat = own.worldTransform

# create a rotation matrix
mat_rot = mathutils.Matrix.Rotation(math.radians(10.0), 4, 'Z')

own.worldTransform = mat * mat_rot

With matrix3x3.rotate() you can only rotate a 3x3 matrix.

thanks for trying :wink:

but unfortunately this script makes a local rotation, not global.

is the global rotation that cannot manage (or, seem a bit complicated)

i want simulate the rotation of the cube at left in the blend using worldTranform


rotGlobal.blend (65.5 KB)

OK. Now I see what you mean.

import bge
import mathutils
import math

cont = bge.logic.getCurrentController()
own = cont.owner

mat = own.worldTransform.to_3x3() #generate a new 3x3 matrix or
#mat = own.worldOrientation 

# create a rotation matrix
rot = mathutils.Matrix.Rotation(math.radians(1.0), 4, 'Z') #or
#rot = mathutils.Euler((0.0, 0.0, math.radians(1.0)), 'XYZ') #or
#rot = mathutils.Quaternion((0.0, 0.0, 1.0), math.radians(1.0))


own.worldOrientation = mat #not necessary if mat = own.worldOrientation used

at the end you use worldOrientation! :smiley: :wink:

that is the “mess”. (“lack ever some piece” as say before)

i had tried to use 3x3 matrix , but then how you “reassign” it to a 4x4?

note that i use a 4x4 that is not a obj (for that i cannot use , worldOrientation ,applyRotation …etc)

Ok. You don’t told me that you don’t have an object.

You can build a composed 4x4 matrix if you multiply a 4x4 translation matrix with a 4x4 rotation matrix.
Instead of .decompose() you can also resize the matrix to a 3x3 matrix for the rotation matrix and for the translation you can also make a copy of the matrix an clear the rotation components.

You can also calculate the global rotation angel (x,y,z) and generate three rotations matrices and multiply it with the 4x4 matrix.

Or calculate the global rotation angel (x,y,z) and then calculate the 9 values for the rotation matrix and set the value in the rows and columns.

import bge
import mathutils
import math

cont = bge.logic.getCurrentController()
own = cont.owner

mat = own.worldTransform

# extract components back out of the matrix
loc, rot, sca = mat.decompose() # Vector, Quaternion, Vector

mat_loc = mathutils.Matrix.Translation(loc)

# create a rotation matrix
rot2 = mathutils.Matrix.Rotation(math.radians(1.0), 4, 'Z') 

mat_rot = rot.to_matrix().to_4x4()

# combine transformations
own.worldTransform = mat_loc * mat_rot

But this ways are more complex then your way.

Thank you HG1! :wink:

very clear your example

thanks for this example!

How would you also compose the scale back into the matrix?

I tried
mat[0][0] *= scale[0]
mat[1][1] *= scale[1]
mat[2][2] *= scale[2]

but the result was quite different (even more after normalization)

never mind, figured it out myself, it needs to be done with a matrix in one step:

import bpyfrom mathutils import Matrix, Vector, Quaternion

m = bpy.context.object.matrix_world

l, r, s = m.decompose()

ll = Matrix.Translation(l)

rr = r.to_matrix().to_4x4()

ss = Matrix(((s[0], 0, 0, 0),
             (0, s[1], 0, 0),
             (0, 0, s[2], 0),
             (0, 0, 0, 1)))
mm = ll * rr * ss

print(str(m) == str(mm)) # True
print(m == mm) # False, floating point inaccuracy

Just a little netiquette. Don’t revive threads if they are more than a month or so old.