diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2009-09-08 02:26:23 +0400 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2009-09-08 02:26:23 +0400 |
commit | 0ab2f675c364f2ca1212b0453bf2ffdce5ebb9ea (patch) | |
tree | 250bc6c6009f27fa1dcaf450dca6b50eb7cc7b3f /source | |
parent | 01eaf4fd5f674858281a253e0a0150d3f44ee325 (diff) |
Fix bug in Mathutil with matrix/matrix and matrix/vector multiplication order.
MathUtil matrix type follows Blender convention of column
major storage. This means that the elements on one column
are contiguous in memory. Vectors are one dimensional
arrays that can be considered in row or in column but
the Blender convention is column so vector should only
be considered as row. This means that the only logical
multiplication operation between matrix and vector is
matrix * vector.
This convention is respected in all parts of MathUtil
except in matrix/matrix and matrix/vector multiplication
where the row major convention is assumed, which in the
and is equivalent to reversing the order of multiplication.
This is clearly a bug and must be corrected but the side
effect is that it will break all scripts using these
operations. Script writers who care about the correctness
of the matrix operations have already implemented work around:
1) change order of matrix/vector multiplication.
vec2 = vec1 * mat1
This must be changed to the normal order:
vec2 = mat1 * vec1
2) change order of matrix/matrix multiplication
(with matl a local transform in matw reference)
mat3 = matl * matw
This must be changed to the normal order:
mat3 = matw * matl
3) transpose before an after the multiplication
matl.transpose()
matw.transpose()
mat3 = matw * matl
mat3.transpose()
This must be changed to:
mat3 = matw * matl;
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/python/generic/matrix.c | 29 | ||||
-rw-r--r-- | source/blender/python/generic/vector.c | 16 |
2 files changed, 23 insertions, 22 deletions
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c index be3e704460a..37d06d0b531 100644 --- a/source/blender/python/generic/matrix.c +++ b/source/blender/python/generic/matrix.c @@ -933,21 +933,21 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) } if(mat1 && mat2) { /*MATRIX * MATRIX*/ - if(mat1->colSize != mat2->rowSize){ + if(mat1->rowSize != mat2->colSize){ PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize"); return NULL; } - for(x = 0; x < mat1->rowSize; x++) { - for(y = 0; y < mat2->colSize; y++) { - for(z = 0; z < mat1->colSize; z++) { - dot += (mat1->matrix[x][z] * mat2->matrix[z][y]); + for(x = 0; x < mat2->rowSize; x++) { + for(y = 0; y < mat1->colSize; y++) { + for(z = 0; z < mat1->rowSize; z++) { + dot += (mat1->matrix[z][y] * mat2->matrix[x][z]); } - mat[((x * mat1->rowSize) + y)] = (float)dot; + mat[((x * mat1->colSize) + y)] = (float)dot; dot = 0.0f; } } - return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW, NULL); + return newMatrixObject(mat, mat2->rowSize, mat1->colSize, Py_NEW, NULL); } if(mat1==NULL){ @@ -1288,9 +1288,9 @@ PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb //----------------column_vector_multiplication (internal)--------- //COLUMN VECTOR Multiplication (Matrix X Vector) -// [1][2][3] [a] -// [4][5][6] * [b] -// [7][8][9] [c] +// [1][4][7] [a] +// [2][5][8] * [b] +// [3][6][9] [c] //vector/matrix multiplication IS NOT COMMUTATIVE!!!! static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec) { @@ -1312,11 +1312,12 @@ static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* for(x = 0; x < vec->size; x++){ vecCopy[x] = vec->vec[x]; - } + } + vecNew[3] = 1.0f; - for(x = 0; x < mat->rowSize; x++) { - for(y = 0; y < mat->colSize; y++) { - dot += mat->matrix[x][y] * vecCopy[y]; + for(x = 0; x < mat->colSize; z++) { + for(y = 0; y < mat->rowSize; y++) { + dot += mat->matrix[y][x] * vecCopy[y]; } vecNew[z++] = (float)dot; dot = 0.0f; diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c index c4a8a37ee05..46a0df4ae4d 100644 --- a/source/blender/python/generic/vector.c +++ b/source/blender/python/generic/vector.c @@ -1955,9 +1955,9 @@ PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_su //-----------------row_vector_multiplication (internal)----------- //ROW VECTOR Multiplication - Vector X Matrix -//[x][y][z] * [1][2][3] -// [4][5][6] -// [7][8][9] +//[x][y][z] * [1][4][7] +// [2][5][8] +// [3][6][9] //vector/matrix multiplication IS NOT COMMUTATIVE!!!! static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) { @@ -1966,7 +1966,7 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat int x, y, z = 0, vec_size = vec->size; if(mat->colSize != vec_size){ - if(mat->rowSize == 4 && vec_size != 3){ + if(mat->colSize == 4 && vec_size != 3){ PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); return NULL; }else{ @@ -1980,11 +1980,11 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat for(x = 0; x < vec_size; x++){ vecCopy[x] = vec->vec[x]; } - + vecNew[3] = 1.0f; //muliplication - for(x = 0; x < mat->colSize; x++) { - for(y = 0; y < mat->rowSize; y++) { - dot += mat->matrix[y][x] * vecCopy[y]; + for(x = 0; x < mat->rowSize; x++) { + for(y = 0; y < mat->colSize; y++) { + dot += mat->matrix[x][y] * vecCopy[y]; } vecNew[z++] = (float)dot; dot = 0.0f; |