Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-11-12 04:38:18 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-11-12 04:38:18 +0300
commita34f525a21eff2ec1f5691ce3ec2056408bacd5d (patch)
tree35dea367c51a94b38a14f35b39b51ee75b243468 /source/blender/python
parent44e36b515660c5521148753632af64307d05b237 (diff)
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.
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/generic/mathutils_matrix.c45
-rw-r--r--source/blender/python/generic/mathutils_quat.c16
-rw-r--r--source/blender/python/generic/mathutils_vector.c90
3 files changed, 75 insertions, 76 deletions
diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c
index c74ec3536e5..4c481e799e2 100644
--- a/source/blender/python/generic/mathutils_matrix.c
+++ b/source/blender/python/generic/mathutils_matrix.c
@@ -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 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
}
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 @@ PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb
}
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);
-}
diff --git a/source/blender/python/generic/mathutils_quat.c b/source/blender/python/generic/mathutils_quat.c
index cb6e6fd3ddd..8a42adce9a9 100644
--- a/source/blender/python/generic/mathutils_quat.c
+++ b/source/blender/python/generic/mathutils_quat.c
@@ -647,7 +647,6 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
{
float quat[QUAT_SIZE], scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
- VectorObject *vec = NULL;
if(QuaternionObject_Check(q1)) {
quat1 = (QuaternionObject*)q1;
@@ -678,19 +677,8 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
}
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);
diff --git a/source/blender/python/generic/mathutils_vector.c b/source/blender/python/generic/mathutils_vector.c
index 57d7ee659d5..2224193914d 100644
--- a/source/blender/python/generic/mathutils_vector.c
+++ b/source/blender/python/generic/mathutils_vector.c
@@ -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 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
/*------------------------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 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
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 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
}
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_mul(PyObject * v1, PyObject * v2)
static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
{
VectorObject *vec = (VectorObject *)v1;
- int i;
float scalar;
if(!BaseMath_ReadCallback(vec))
@@ -1102,20 +1145,28 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
/* 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 @@ if len(unique) != len(items):
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 @@ static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObj
}
return 0;
}
+#endif
/*----------------------------Vector.negate() -------------------- */
static char Vector_Negate_doc[] =