[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23052] branches/blender2.5/blender/source /blender/python/generic: Fix bug in Mathutil with matrix/matrix and matrix/ vector multiplication order.

Benoit Bolsee benoit.bolsee at online.be
Tue Sep 8 00:26:24 CEST 2009


Revision: 23052
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23052
Author:   ben2610
Date:     2009-09-08 00:26:23 +0200 (Tue, 08 Sep 2009)

Log Message:
-----------
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;

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/python/generic/matrix.c
    branches/blender2.5/blender/source/blender/python/generic/vector.c

Modified: branches/blender2.5/blender/source/blender/python/generic/matrix.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/generic/matrix.c	2009-09-07 18:44:01 UTC (rev 23051)
+++ branches/blender2.5/blender/source/blender/python/generic/matrix.c	2009-09-07 22:26:23 UTC (rev 23052)
@@ -933,21 +933,21 @@
 	}
 
 	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 @@
 
 //----------------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 @@
 
 	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;

Modified: branches/blender2.5/blender/source/blender/python/generic/vector.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/generic/vector.c	2009-09-07 18:44:01 UTC (rev 23051)
+++ branches/blender2.5/blender/source/blender/python/generic/vector.c	2009-09-07 22:26:23 UTC (rev 23052)
@@ -1955,9 +1955,9 @@
 
 //-----------------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 @@
 	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 @@
 	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;





More information about the Bf-blender-cvs mailing list