[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [33029] trunk/blender/source/blender/ python/generic: bugfix [#24660] (vector * matrix) fails, (matrix * vector) succeeds

Campbell Barton ideasman42 at gmail.com
Fri Nov 12 02:38:18 CET 2010


Revision: 33029
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=33029
Author:   campbellbarton
Date:     2010-11-12 02:38:18 +0100 (Fri, 12 Nov 2010)

Log Message:
-----------
bugfix [#24660] (vector * matrix) fails, (matrix * vector) succeeds

- Reverse vector * matrix multiplication order. now this matches how numpy works.
- Disallow 'matrix * vec' and 'quat * vec', now it raises an error.
- Add missing in-place multiply 'vec *= quat'

Many scripts will need to be updated for this but at least it will error rather then failing silently.

Modified Paths:
--------------
    trunk/blender/source/blender/python/generic/mathutils_matrix.c
    trunk/blender/source/blender/python/generic/mathutils_quat.c
    trunk/blender/source/blender/python/generic/mathutils_vector.c

Modified: trunk/blender/source/blender/python/generic/mathutils_matrix.c
===================================================================
--- trunk/blender/source/blender/python/generic/mathutils_matrix.c	2010-11-11 23:36:56 UTC (rev 33028)
+++ trunk/blender/source/blender/python/generic/mathutils_matrix.c	2010-11-12 01:38:18 UTC (rev 33029)
@@ -31,9 +31,6 @@
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
 
-static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); /* utility func */
-
-
 /* matrix vector callbacks */
 int mathutils_matrix_vector_cb_index= -1;
 
@@ -1568,7 +1565,8 @@
 	}
 	else /* if(mat1) { */ {
 		if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */
-			return column_vector_multiplication(mat1, (VectorObject *)m2); /* vector update done inside the function */
+			PyErr_SetString(PyExc_TypeError, "Matrix multiplication: Only 'vec * matrix' is supported, not the reverse.");
+			return NULL;
 		}
 		else {
 			scalar= PyFloat_AsDouble(m2);
@@ -1945,42 +1943,3 @@
 	}
 	return (PyObject *) self;
 }
-
-//----------------column_vector_multiplication (internal)---------
-//COLUMN VECTOR Multiplication (Matrix X Vector)
-// [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)
-{
-	float vecNew[4], vecCopy[4];
-	double dot = 0.0f;
-	int x, y, z = 0;
-
-	if(!BaseMath_ReadCallback(mat) || !BaseMath_ReadCallback(vec))
-		return NULL;
-	
-	if(mat->rowSize != vec->size){
-		if(mat->rowSize == 4 && vec->size != 3){
-			PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
-			return NULL;
-		}else{
-			vecCopy[3] = 1.0f;
-		}
-	}
-
-	for(x = 0; x < vec->size; x++){
-		vecCopy[x] = vec->vec[x];
-	}
-	vecNew[3] = 1.0f;
-
-	for(x = 0; x < mat->colSize; x++) {
-		for(y = 0; y < mat->rowSize; y++) {
-			dot += mat->matrix[y][x] * vecCopy[y];
-		}
-		vecNew[z++] = (float)dot;
-		dot = 0.0f;
-	}
-	return newVectorObject(vecNew, vec->size, Py_NEW, NULL);
-}

Modified: trunk/blender/source/blender/python/generic/mathutils_quat.c
===================================================================
--- trunk/blender/source/blender/python/generic/mathutils_quat.c	2010-11-11 23:36:56 UTC (rev 33028)
+++ trunk/blender/source/blender/python/generic/mathutils_quat.c	2010-11-12 01:38:18 UTC (rev 33029)
@@ -647,7 +647,6 @@
 {
 	float quat[QUAT_SIZE], scalar;
 	QuaternionObject *quat1 = NULL, *quat2 = NULL;
-	VectorObject *vec = NULL;
 
 	if(QuaternionObject_Check(q1)) {
 		quat1 = (QuaternionObject*)q1;
@@ -678,19 +677,8 @@
 	}
 	else { /* QUAT*SOMETHING */
 		if(VectorObject_Check(q2)){  /* QUAT*VEC */
-			float tvec[3];
-			vec = (VectorObject*)q2;
-			if(vec->size != 3){
-				PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
-				return NULL;
-			}
-			if(!BaseMath_ReadCallback(vec)) {
-				return NULL;
-			}
-
-			copy_v3_v3(tvec, vec->vec);
-			mul_qt_v3(quat1->quat, tvec);
-			return newVectorObject(tvec, 3, Py_NEW, NULL);
+			PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: Only 'vector * quaternion' is supported, not the reverse");
+			return NULL;
 		}
 		
 		scalar= PyFloat_AsDouble(q2);

Modified: trunk/blender/source/blender/python/generic/mathutils_vector.c
===================================================================
--- trunk/blender/source/blender/python/generic/mathutils_vector.c	2010-11-11 23:36:56 UTC (rev 33028)
+++ trunk/blender/source/blender/python/generic/mathutils_vector.c	2010-11-12 01:38:18 UTC (rev 33029)
@@ -39,7 +39,6 @@
 #define SWIZZLE_VALID_AXIS 0x4
 #define SWIZZLE_AXIS       0x3
 
-static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObject * mat); /* utility func */
 static PyObject *Vector_ToTupleExt(VectorObject *self, int ndigits);
 
 //----------------------------------mathutils.Vector() ------------------
@@ -1007,6 +1006,47 @@
 
 /*------------------------obj * obj------------------------------
   mulplication*/
+
+
+/* COLUMN VECTOR Multiplication (Vector X Matrix)
+ * [a] * [1][4][7]
+ * [b] * [2][5][8]
+ * [c] * [3][6][9]
+ *
+ * note: vector/matrix multiplication IS NOT COMMUTATIVE!!!!
+ * note: assume read callbacks have been done first.
+ */
+static int column_vector_multiplication(float *rvec, VectorObject* vec, MatrixObject * mat)
+{
+	float vecCopy[4];
+	double dot = 0.0f;
+	int x, y, z = 0;
+	
+	if(mat->rowSize != vec->size){
+		if(mat->rowSize == 4 && vec->size != 3){
+			PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
+			return -1;
+		}else{
+			vecCopy[3] = 1.0f;
+		}
+	}
+
+	for(x = 0; x < vec->size; x++){
+		vecCopy[x] = vec->vec[x];
+	}
+	rvec[3] = 1.0f;
+
+	for(x = 0; x < mat->colSize; x++) {
+		for(y = 0; y < mat->rowSize; y++) {
+			dot += mat->matrix[y][x] * vecCopy[y];
+		}
+		rvec[z++] = (float)dot;
+		dot = 0.0f;
+	}
+	
+	return 0;
+}
+
 static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
 {
 	VectorObject *vec1 = NULL, *vec2 = NULL;
@@ -1050,17 +1090,21 @@
 		vec1= vec2;
 		v2= v1;
 	}
-	
+
 	if (MatrixObject_Check(v2)) {
 		/* VEC * MATRIX */
-		float tvec[4];
-		if(row_vector_multiplication(tvec, vec1, (MatrixObject*)v2) == -1)
+		float tvec[MAX_DIMENSIONS];
+		if(!BaseMath_ReadCallback((MatrixObject *)v2))
 			return NULL;
-		return newVectorObject(tvec, vec1->size, Py_NEW, NULL);
+		if(column_vector_multiplication(tvec, vec1, (MatrixObject*)v2) == -1) {
+			return NULL;
+		}
+
+		return newVectorObject(tvec, 3, Py_NEW, NULL);
 	} else if (QuaternionObject_Check(v2)) {
 		/* VEC * QUAT */
 		QuaternionObject *quat2 = (QuaternionObject*)v2;
-		float tvec[4];
+		float tvec[3];
 
 		if(vec1->size != 3) {
 			PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
@@ -1075,7 +1119,7 @@
 	}
 	else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*FLOAT */
 		int i;
-		float vec[4];
+		float vec[MAX_DIMENSIONS];
 		
 		for(i = 0; i < vec1->size; i++) {
 			vec[i] = vec1->vec[i] * scalar;
@@ -1093,7 +1137,6 @@
 static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
 {
 	VectorObject *vec = (VectorObject *)v1;
-	int i;
 	float scalar;
 	
 	if(!BaseMath_ReadCallback(vec))
@@ -1102,20 +1145,28 @@
 	/* only support vec*=float and vec*=mat
 	   vec*=vec result is a float so that wont work */
 	if (MatrixObject_Check(v2)) {
-		float tvec[4];
-		if(row_vector_multiplication(tvec, vec, (MatrixObject*)v2) == -1)
+		if(!BaseMath_ReadCallback((MatrixObject *)v2))
 			return NULL;
+		
+		if(column_vector_multiplication(vec->vec, vec, (MatrixObject*)v2) == -1)
+			return NULL;
+	}
+	else if (QuaternionObject_Check(v2)) {
+		/* VEC *= QUAT */
+		QuaternionObject *quat2 = (QuaternionObject*)v2;
 
-		i= vec->size - 1;
-		do {
-			vec->vec[i] = tvec[i];
-		} while(i--);
+		if(vec->size != 3) {
+			PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
+			return NULL;
+		}
+
+		if(!BaseMath_ReadCallback(quat2)) {
+			return NULL;
+		}
+		mul_qt_v3(quat2->quat, vec->vec);
 	}
 	else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*=FLOAT */
-		i= vec->size - 1;
-		do {
-			vec->vec[i] *=	scalar;
-		} while(i--);		
+		mul_vn_fl(vec->vec, vec->size, scalar);
 	}
 	else {
 		PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
@@ -2010,7 +2061,7 @@
 	print "ERROR"
 */
 
-//-----------------row_vector_multiplication (internal)-----------
+#if 0
 //ROW VECTOR Multiplication - Vector X Matrix
 //[x][y][z] *  [1][4][7]
 //             [2][5][8]
@@ -2048,6 +2099,7 @@
 	}
 	return 0;
 }
+#endif
 
 /*----------------------------Vector.negate() -------------------- */
 static char Vector_Negate_doc[] =





More information about the Bf-blender-cvs mailing list