Problem with getMatrix()

Hi to all!
I’m a newbie, so please excuse me for basic question.

I must convert the verts and norms from local to global coords.

So I use this code:


objects = Object.GetSelected()
mesh = objects[0].getData()
m = objects[0].getMatrix()

for v in mesh.verts:
    vCoo = mulmatvec3x3(m, v.co)
    vNor = mulmatvec3x3(m, v.no)

where the mulmatvec3x3 is:


def mulmatvec3x3(m, v):
    r = [0.0, 0.0, 0.0]
    r[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0]
    r[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1]
    r[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2]
    return r

The code above don’t work. The verts isn’t modified, as multiplied for a identity matrix…

I’ve added a print m, so I’ve understand the mistake (I hope): getMatrix return a 4x4 matrix. In istance, if I move the object along Y axe, the matrix is:


[1.0000, 0.0000, -0.0000, 0.0000]
[0.0000, 1.0000, 0.0000, 0.0000]
[0.0000, 0.0000, 1.0000, 0.0000]
[0.0000, 12.4396, 0.0000, 1.0000]

Anyone can help me ?
I’m right about the mistake?
Anyone have the 4x4 mult code?

Thanks to all!

hi, I think that at this threat there is the answer to your questions…just have a look

https://blenderartists.org/forum/viewtopic.php?t=15284&highlight=getmatrix

hope this helps
manne

I’m not the best person to talk about matrix. Even if i had a class on that. :x
There is some matrix function in Mathutils. Have a look:
http://www.blender.org/modules/documentation/236PythonDoc/Mathutils-module.html

I had this lying around, I’ve mentioned it elsewhere
[it also applies the offset, not just the rotation]

import Blender

def applyMatrix(mesh,mat):
	# apply the deformation to each vert
	for vert in mesh.verts:
		# I'd rather do something like:
		#vert.co = Blender.Mathutils.MatMultVec(mat,vert.co)
		co = vert.co[:]
		for i in range(3):
			vert.co[i] = mat[0][i]*co[0] + mat[1][i]*co[1] + mat[2][i]*co[2] + mat[3][i]

## apply matrix of object to all verts, and transformations likely causing matrix
## doesn't remove object parent
def applyDef(obj):
	mat = obj.getMatrix('worldspace')
	mesh = obj.getData()
	applyMatrix(mesh,mat)
	# remove location/rotation from object
	obj.setLocation(0.0,0.0,0.0)
	obj.setEuler([0.0,0.0,0.0])
	mesh.update()

for obj in Blender.Object.GetSelected():
	if obj.getType() == "Mesh":
		applyDef(obj)

it looks like this code is your problem


objects = Object.GetSelected()
mesh = objects[0].getData()
m = objects[0].getMatrix()

for v in mesh.verts:
    vCoo = mulmatvec3x3(m, v.co)
    vNor = mulmatvec3x3(m, v.no)

should be


objects = Object.GetSelected()
mesh = objects[0].getData()
m = objects[0].getMatrix()

for v in mesh.verts:
    v.co = mulmatvec3x3(m, v.co)
    v.no = mulmatvec3x3(m, v.no)

because you weren’t changing the verts… [I didn’t check if it works though]

Hi,

For coordinate transformations, you should use mulmatvec4x3 instead of mulmatvec3x3.

See eg the knifescript.

# matrix(4x3) vector multiplication
def mulmatvec4x3(a, b):
# a is vector, b is matrix
r = [0, 0, 0]
r[0] = a[0]*b[0][0] + a[1]*b[1][0] + a[2]*b[2][0] + b[3][0]
r[1] = a[0]*b[0][1] + a[1]*b[1][1] + a[2]*b[2][1] + b[3][1]
r[2] = a[0]*b[0][2] + a[1]*b[1][2] + a[2]*b[2][2] + b[3][2]
return r

For manne73:

Thanks to your link, I’ve realized that my code scale and rotate the verts, simply don’t translate it. This because the 3x3mult don’t get the last line of matrix.

For Gabio: Thanks

For z3r0 d:

Thanks, but the code:


objects = Object.GetSelected() 
mesh = objects[0].getData() 
m = objects[0].getMatrix() 

for v in mesh.verts: 
    v.co = mulmatvec3x3(m, v.co) 
    v.no = mulmatvec3x3(m, v.no) 

Don’t solve the problem, because it use the 3x3 multiplication instead 4x4. Besides, this code modify the object verts.

For Tuinbels:

This seem to multiply a matrix (4x3) with a 3 dimension vector. However getMatrix return a 4x4 matrix, not 4x3. I’m confused…

THANKS TO ALL!

No worries, you only need the first 3 columns.

Don’t remeber what the fourth column was for (rotation maybe?), but that one is not necessary for coordinate transformations.

Just give it a try. You’ll see it works. :slight_smile:

Greetings

wim

actually, it is

it is translation, the first 3 columns are rotation

3x3 matrix: rotation only
4x4 matrix: rotation and translation

OK. I’ve understand.
The Blender Matrix use the homogeneus coordinate system.
To convert a verts from local to global, the multiplication should be:


v[              m[
   a,              [a0,b0,c0,0]
   b,   *         [a1,b1,c1,0]
   c,              [a2,b2,c2,0]
   1              [a3,b3,c3,1]
 ]                ]

In the homogeneus system the 0 or 1 as last component is to indicate the tuple is a vector or not. In istance, v is a vector, as the [a3,b3,c3,1] (translation vector).

The multiplication should be:


def multmatvec4x3(m, v):
        r = [0.0, 0.0, 0.0,1]
        r[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0] + v[3]*m[3][0]
        r[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1] + v[3]* m[3][1]
        r[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2] + v[3]*m[3][2]
        r[3] = v[0]*m[0][3] + v[1]*m[1][3] + v[2]*m[2][3] + v[3]*m[3][3]
	return r

However, because r[3] is always 1, and v3 is always 1, this can be semplified as the famous 4x3 matrix:


def multmatvec4x3(m, v):
	r = [0.0, 0.0, 0.0]
	r[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0] + m[3][0]
	r[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1] + m[3][1]
	r[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2] + m[3][2]
	return r

That work fine with 4x4 blender matrix.

However in previous message I tell it don’t work because was another error: the normals must be not transformed using the translations.

Now all work fine.
Thanks!