[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [31539] trunk/blender/source/blender/ python: bugfix [#23454] vector*matrix not the same as vector*=matrix

Campbell Barton ideasman42 at gmail.com
Tue Aug 24 00:10:13 CEST 2010


Revision: 31539
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=31539
Author:   campbellbarton
Date:     2010-08-24 00:10:13 +0200 (Tue, 24 Aug 2010)

Log Message:
-----------
bugfix [#23454] vector*matrix not the same as vector*=matrix
- they now share the same code so it wont happen again.
- added id_data to properties so we can do...
  matrix = C.object.matrix_world
  obj = matrix.owner.id_data # get the original object back.

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

Modified: trunk/blender/source/blender/python/generic/mathutils_matrix.c
===================================================================
--- trunk/blender/source/blender/python/generic/mathutils_matrix.c	2010-08-23 21:31:57 UTC (rev 31538)
+++ trunk/blender/source/blender/python/generic/mathutils_matrix.c	2010-08-23 22:10:13 UTC (rev 31539)
@@ -1526,7 +1526,6 @@
 		return NULL;
 	}
 	else /* if(mat1) { */ {
-		
 		if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */
 			return column_vector_multiplication(mat1, (VectorObject *)m2); /* vector update done inside the function */
 		}

Modified: trunk/blender/source/blender/python/generic/mathutils_vector.c
===================================================================
--- trunk/blender/source/blender/python/generic/mathutils_vector.c	2010-08-23 21:31:57 UTC (rev 31538)
+++ trunk/blender/source/blender/python/generic/mathutils_vector.c	2010-08-23 22:10:13 UTC (rev 31539)
@@ -39,7 +39,7 @@
 #define SWIZZLE_VALID_AXIS 0x4
 #define SWIZZLE_AXIS       0x3
 
-static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */
+static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObject * mat); /* utility func */
 static PyObject *Vector_ToTupleExt(VectorObject *self, int ndigits);
 
 //----------------------------------mathutils.Vector() ------------------
@@ -1002,7 +1002,11 @@
 		return PyFloat_FromDouble(dot);
 	}
 	
-	/*swap so vec1 is always the vector */
+	/* swap so vec1 is always the vector */
+	/* note: it would seem from this code that the matrix multiplication below
+	 * is non-communicative. however the matrix object will always handle the
+	 * (matrix * vector) case.
+	 * This is NOT so for Quaternions: TODO, check if communicative (vec * quat) is correct */
 	if (vec2) {
 		vec1= vec2;
 		v2= v1;
@@ -1010,7 +1014,10 @@
 	
 	if (MatrixObject_Check(v2)) {
 		/* VEC * MATRIX */
-		return row_vector_multiplication(vec1, (MatrixObject*)v2);
+		float tvec[4];
+		if(row_vector_multiplication(tvec, vec1, (MatrixObject*)v2) == -1)
+			return NULL;
+		return newVectorObject(tvec, vec1->size, Py_NEW, NULL);
 	} else if (QuaternionObject_Check(v2)) {
 		/* VEC * QUAT */
 		QuaternionObject *quat2 = (QuaternionObject*)v2;
@@ -1056,42 +1063,20 @@
 	/* only support vec*=float and vec*=mat
 	   vec*=vec result is a float so that wont work */
 	if (MatrixObject_Check(v2)) {
-		float vecCopy[4];
-		int x,y, size = vec->size;
-		MatrixObject *mat= (MatrixObject*)v2;
-		
-		if(!BaseMath_ReadCallback(mat))
+		float tvec[4];
+		if(row_vector_multiplication(tvec, vec, (MatrixObject*)v2) == -1)
 			return NULL;
-		
-		if(mat->colSize != size){
-			if(mat->rowSize == 4 && vec->size != 3){
-				PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
-				return NULL;
-			} else {
-				vecCopy[3] = 1.0f;
-			}
-		}
-		
-		for(i = 0; i < size; i++){
-			vecCopy[i] = vec->vec[i];
-		}
-		
-		size = MIN2(size, mat->colSize);
-		
-		/*muliplication*/
-		for(x = 0, i = 0; x < size; x++, i++) {
-			double dot = 0.0f;
-			for(y = 0; y < mat->rowSize; y++) {
-				dot += mat->matrix[y][x] * vecCopy[y];
-			}
-			vec->vec[i] = (float)dot;
-		}
+
+		i= vec->size - 1;
+		do {
+			vec->vec[i] = tvec[i];
+		} while(i--);
 	}
 	else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*=FLOAT */
-		
-		for(i = 0; i < vec->size; i++) {
+		i= vec->size - 1;
+		do {
 			vec->vec[i] *=	scalar;
-		}
+		} while(i--);		
 	}
 	else {
 		PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
@@ -1992,37 +1977,37 @@
 //             [2][5][8]
 //             [3][6][9]
 //vector/matrix multiplication IS NOT COMMUTATIVE!!!!
-static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
+static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObject * mat)
 {
-	float vecNew[4], vecCopy[4];
+	float vecCopy[4];
 	double dot = 0.0f;
 	int x, y, z = 0, vec_size = vec->size;
 
 	if(mat->colSize != vec_size){
 		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;
+			return -1;
 		}else{
 			vecCopy[3] = 1.0f;
 		}
 	}
 	
 	if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat))
-		return NULL;
+		return -1;
 	
 	for(x = 0; x < vec_size; x++){
 		vecCopy[x] = vec->vec[x];
 	}
-	vecNew[3] = 1.0f;
+	rvec[3] = 1.0f;
 	//muliplication
 	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;
+		rvec[z++] = (float)dot;
 		dot = 0.0f;
 	}
-	return newVectorObject(vecNew, vec_size, Py_NEW, NULL);
+	return 0;
 }
 
 /*----------------------------Vector.negate() -------------------- */

Modified: trunk/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_rna.c	2010-08-23 21:31:57 UTC (rev 31538)
+++ trunk/blender/source/blender/python/intern/bpy_rna.c	2010-08-23 22:10:13 UTC (rev 31539)
@@ -2645,8 +2645,9 @@
 	return ret;
 }
 
-static PyObject *pyrna_struct_get_id_data(BPy_StructRNA *self)
+static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self)
 {
+	/* used for struct and pointer since both have a ptr */
 	if(self->ptr.id.data) {
 		PointerRNA id_ptr;
 		RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr);
@@ -2659,13 +2660,13 @@
 /*****************************************************************************/
 /* Python attributes get/set structure:                                      */
 /*****************************************************************************/
-#if 0
+
 static PyGetSetDef pyrna_prop_getseters[] = {
-	{"active", (getter)pyrna_prop_get_active, (setter)pyrna_prop_set_active, "", NULL},
+	{"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, "The :class:`ID` object this datablock is from or None, (not available for all data types)", NULL},
 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
 };
-#endif
 
+
 static PyGetSetDef pyrna_struct_getseters[] = {
 	{"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, "The :class:`ID` object this datablock is from or None, (not available for all data types)", NULL},
 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
@@ -3725,7 +3726,7 @@
   /*** Attribute descriptor and subclassing stuff ***/
 	pyrna_prop_methods,			/* struct PyMethodDef *tp_methods; */
 	NULL,                       /* struct PyMemberDef *tp_members; */
-	NULL /*pyrna_prop_getseters*/,      	/* struct PyGetSetDef *tp_getset; */
+	pyrna_prop_getseters,      	/* struct PyGetSetDef *tp_getset; */
 	NULL,                       /* struct _typeobject *tp_base; */
 	NULL,                       /* PyObject *tp_dict; */
 	NULL,                       /* descrgetfunc tp_descr_get; */





More information about the Bf-blender-cvs mailing list