8
$\begingroup$

In my script I am trying to store a Matrix, for example the region_3d.view_matrix of a 3D view. This returns:

Matrix(((0.04198726266622543, 0.9991182684898376, 3.666877432806359e-07, -0.32331380248069763),
        (-0.349155992269516, 0.014672632329165936, 0.9369498491287231, -0.4471516013145447),
        (0.9361235499382019, -0.03934017941355705, 0.3494640588760376, 0.5855286717414856),
        (0.0, 0.0, 0.0, 1.0)))

How can I store this in one of Blender's bpy.props properties for access later? I thought FloatVectorProperty was closest, but that was just a guess and depending on what I try it complains either that I'm providing tuples or that it only wants 3 items, not 4.

$\endgroup$
3
  • $\begingroup$ hmm, It might sound stupid but if you just need to store it for access why don't you just declare it in a python object. $\endgroup$
    – Yvain
    Apr 11, 2016 at 19:42
  • $\begingroup$ @Yvain Will that survive saving and reloading the blend file? $\endgroup$ Apr 11, 2016 at 20:21
  • $\begingroup$ No chance, it will actually disappear as soon as you stop the script even while remaining in blender. Unless you set your python script to write the variable on an output text file $\endgroup$
    – Yvain
    Apr 12, 2016 at 8:01

2 Answers 2

6
$\begingroup$

I haven't tested this extensively, but it looks like you can store a matrix as an "ID" property rather than a bpy.props property. I stored a matrix like this from the Python console:

>>> C.object['matrix'] = m

where m was a 4x4 matrix

It appears that it was actually stored as an array of four arrays:

>>> C.object['matrix']
[<bpy id property array [4]>, <bpy id property array [4]>,
<bpy id property array [4]>, <bpy id property array [4]>]

I saved the file and reopened it, and the value was still intact. It can even be typecast back to a Matrix:

>>> Matrix(C.object['matrix'])
Matrix(((0.68588, -0.31737, 0.65486, 7.48113),
        (0.72763, 0.31246, -0.61066, -6.50763),
        (-0.01081, 0.89534, 0.44524, 5.34366),
        (0.0, 0.0, 0.0, 1.0)))

(I truncated the precision of the numbers for readability).

$\endgroup$
11
$\begingroup$

If you choose MATRIX as subtype the property will return a mathutils.Matrix object on access. So you might define a utility function to set the attribute

import bpy
from mathutils import Matrix

def flatten(mat):
    dim = len(mat)
    return [mat[j][i] for i in range(dim) 
                      for j in range(dim)]

bpy.types.Scene.matrix_property = bpy.props.FloatVectorProperty(
    name="Matrix",
    size=16,
    subtype="MATRIX")

mat = Matrix([[i + j for j in range(4)]
                     for i in range(0, 16, 4)])

scene = bpy.context.scene
scene.matrix_property = flatten(mat)

print(mat)
print(scene.matrix_property)
$\endgroup$
3
  • 1
    $\begingroup$ Took me a while to understand what flattern was doing, but I get it now. Is it strange there is no built in way to flatten a Matrix? $\endgroup$ Apr 12, 2016 at 11:11
  • $\begingroup$ Just an into this, very weird indeed. Thanks @pink-vertex $\endgroup$
    – MACHIN3
    May 21, 2018 at 18:12
  • $\begingroup$ If your mat is a numpy array you can use scene.matrix_property = mat.flatten("F").tolist() $\endgroup$ May 7, 2023 at 13:34

You must log in to answer this question.

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