1
$\begingroup$

I'm taking a computer graphics course. In one assignment I had to check if a matrix transformation maps points to another set of points

I thought that the best way to learn how this was to use Blender's Python API and try doing this.

These are my set of points

t0 = (−1, −1, −1)

t1 = (1, 1, −1)

t2 = (−1, 1, 1) 

t3 = (1, −1, 1) 

The set of points I want to get mapped to are

u0 = (2, 2, −1)

u1 = (2, 2, 3)

u2 = (0, 0, 1)

u3 = (4, 0, 1)

and the transformation:

Rotation about the z-axis by 45°, then scaling with sx =√2, sy =√2, sz = 1, then translation by (2, 1, −1), and then rotation about the x-axis by 90 degree.

I created the two objects for the two set of objects. And I want to move the object t (with vertices t0,t1 ...) to the object u (with vertices u0, u1 ...)

#rotation around Z axis
rot_mat = Matrix.Rotation(radians(90), 4, 'Z') 

# decompose world_matrix's components
orig_loc, orig_rot, orig_scale = obj.matrix_world.decompose()
#create the translation vector
translation =  mathutils.Vector((2,1,-1))
new_loc = orig_loc + translation
orig_loc_mat = Matrix.Translation(new_loc)
orig_rot_mat = orig_rot.to_matrix().to_4x4()
orig_scale_mat = Matrix.Scale(orig_scale[0],4,(sqrt(2),0,0)) * 
Matrix.Scale(orig_scale[1],4,(0,1,0)) * 
Matrix.Scale(orig_scale[2],4(0,0,sqrt(2)))

obj.matrix_world = orig_loc_mat * rot_mat * orig_rot_mat * 
orig_scale_mat 

This is not working, the object gets mapped to a wrong position. The blue object is the object from t coordinates, the red from the u coordinates, the green one should be overlapping the red one.

enter image description here What am I missing?

$\endgroup$

2 Answers 2

2
$\begingroup$

enter image description here

You need to apply the matrices in reverse order.

The code is given below. You can comment the last call (and the createObjs call if the objects are already created) and uncomment the commented applyMatToVerts calls one by one to see the effect of each matrix transformation (see gif above). The last applyMatToVerts call is equivalent of all the commented calls. It creates a single matrix and applies it to all the coordinates of the object. I am not using matrix world since the objects are at the origin. If they are not, the matrices need to be multiplied with obj.matrix_world.

import bpy
import bmesh
from math import radians, sqrt
from mathutils import Matrix

def getMat(name, color):
    oldMat = bpy.data.materials.get(name)
    if(oldMat != None):
        bpy.data.materials.remove(oldMat)
    mat = bpy.data.materials.new(name)
    mat.diffuse_color = color
    return mat

def createObjFromCo(meshName, objName, coList, matName, matColor):
    bm = bmesh.new()
    verts = []
    for co in coList:
        verts.append(bm.verts.new(co))
    bm.faces.new(verts)
    mesh = bpy.data.meshes.new(meshName)
    obj = bpy.data.objects.new(objName, mesh)
    bpy.context.scene.objects.link(obj)
    bm.to_mesh(mesh)
    mat = getMat(matName, matColor)
    obj.data.materials.append(mat)
    return obj

def applyMatToVerts(obj, mat):
    for vert in obj.data.vertices:
        vert.co = mat * vert.co

origObjName = 'origObj'
origCopyName = 'origCopyObj'
toMapObjName = 'toMapObj'

def createObjs():
    t = [(-1, -1, -1), (1, 1, -1), (-1, 1, 1), (1, -1, 1)]
    u = [(2, 2, -1), (2, 2, 3), (0, 0, 1), (4, 0, 1)]
    orange = (0.8, 0.2, 0.1)
    green = (0.2, 0.8, 0.2)
    blue = (0.2, 0.2, 0.8)
    origObj = createObjFromCo(origObjName+'_data', origObjName, t, '__obj1Mat__', orange)
    origCopy = createObjFromCo(origCopyName+'_data', origCopyName, t, '__objCopyMat__', blue)
    toMapObj = createObjFromCo(toMapObjName+'_data', toMapObjName, u, '__obj2Mat__',green)

createObjs()

origObj = bpy.data.objects['origObj']
origCopy = bpy.data.objects['origCopyObj']
toMapObj = bpy.data.objects['toMapObj']

rot_mat1 = Matrix.Rotation(radians(45), 4, 'Z') 
scale_mat1 = Matrix.Scale(sqrt(2), 4, (1,0,0))
scale_mat2 = Matrix.Scale(sqrt(2), 4, (0,1,0))
trans_mat = Matrix.Translation((2, 1, -1))
rot_mat2 = Matrix.Rotation(radians(90), 4, 'X') 

# ~ applyMatToVerts(origCopy, rot_mat1)
# ~ applyMatToVerts(origCopy, scale_mat1)
# ~ applyMatToVerts(origCopy, scale_mat2)
# ~ applyMatToVerts(origCopy, trans_mat)
# ~ applyMatToVerts(origCopy, rot_mat2)


applyMatToVerts(origCopy, rot_mat2 * trans_mat * scale_mat1 * scale_mat2 * rot_mat1)
$\endgroup$
0
0
$\begingroup$

I hope it is not too late, but as far as I remember, matrix multiplication in python requires '@' instead of '*'. For me, this worked instantly

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .