diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-01-23 11:37:34 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-01-23 11:37:34 +0300 |
commit | 552b36733bb2015aa64933bf3c57f1ad90c87b5a (patch) | |
tree | 36e68c34de612538b154d9b711aee6e1593ef124 /source/blender | |
parent | a877155a7c2359b1984641ff9225f259de48611c (diff) |
bugfix + minor mathutils.Vector edits.
- multiplying a 2D vector by a 3x3 or 4x4 matrix would use un-initialized memory, now throw an exception.
- use more variable length array BLI_math functions.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenlib/BLI_math_vector.h | 1 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_vector.c | 8 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_vector.c | 144 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_vector.h | 2 |
4 files changed, 67 insertions, 88 deletions
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 35b7939329a..5a5d518940d 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -176,6 +176,7 @@ void mul_vn_fl(float *array, const int size, const float f); void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f); void add_vn_vn(float *array_tar, const float *array_src, const int size); void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size); +void sub_vn_vn(float *array_tar, const float *array_src, const int size); void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size); void fill_vni(int *array_tar, const int size, const int val); void fill_vn(float *array_tar, const int size, const float val); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 539d3fb97f6..37a68cb0fca 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -407,6 +407,14 @@ void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_ while(i--) { *(tar--) = *(src_a--) + *(src_b--); } } +void sub_vn_vn(float *array_tar, const float *array_src, const int size) +{ + float *tar= array_tar + (size-1); + const float *src= array_src + (size-1); + int i= size; + while(i--) { *(tar--) -= *(src--); } +} + void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size) { float *tar= array_tar + (size-1); diff --git a/source/blender/python/generic/mathutils_vector.c b/source/blender/python/generic/mathutils_vector.c index a3bf1471813..de6002859d3 100644 --- a/source/blender/python/generic/mathutils_vector.c +++ b/source/blender/python/generic/mathutils_vector.c @@ -76,11 +76,8 @@ static char Vector_Zero_doc[] = static PyObject *Vector_Zero(VectorObject *self) { - int i; - for(i = 0; i < self->size; i++) { - self->vec[i] = 0.0f; - } - + fill_vn(self->vec, self->size, 0.0f); + (void)BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; @@ -780,7 +777,6 @@ static PyObject *Vector_item(VectorObject *self, int i) return NULL; return PyFloat_FromDouble(self->vec[i]); - } /*----------------------------object[]------------------------- sequence accessor (set)*/ @@ -861,43 +857,34 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, addition*/ static PyObject *Vector_add(PyObject * v1, PyObject * v2) { - int i; - float vec[4]; - VectorObject *vec1 = NULL, *vec2 = NULL; - - if VectorObject_Check(v1) - vec1= (VectorObject *)v1; - - if VectorObject_Check(v2) - vec2= (VectorObject *)v2; - - /* make sure v1 is always the vector */ - if (vec1 && vec2 ) { - - if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) - return NULL; - - /*VECTOR + VECTOR*/ - if(vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation"); - return NULL; - } - for(i = 0; i < vec1->size; i++) { - vec[i] = vec1->vec[i] + vec2->vec[i]; - } - return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); + float vec[MAX_DIMENSIONS]; + + if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { + PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation"); + return NULL; } - - PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation"); - return NULL; + vec1 = (VectorObject*)v1; + vec2 = (VectorObject*)v2; + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; + + /*VECTOR + VECTOR*/ + if(vec1->size != vec2->size) { + PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation"); + return NULL; + } + + add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); + + return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); } /* ------------------------obj += obj------------------------------ addition in place */ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) { - int i; VectorObject *vec1 = NULL, *vec2 = NULL; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { @@ -915,12 +902,10 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; - for(i = 0; i < vec1->size; i++) { - vec1->vec[i] = vec1->vec[i] + vec2->vec[i]; - } + add_vn_vn(vec1->vec, vec2->vec, vec1->size); (void)BaseMath_WriteCallback(vec1); - Py_INCREF( v1 ); + Py_INCREF(v1); return v1; } @@ -928,9 +913,8 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) subtraction*/ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) { - int i; - float vec[4]; VectorObject *vec1 = NULL, *vec2 = NULL; + float vec[MAX_DIMENSIONS]; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation"); @@ -946,9 +930,8 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation"); return NULL; } - for(i = 0; i < vec1->size; i++) { - vec[i] = vec1->vec[i] - vec2->vec[i]; - } + + sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); } @@ -957,8 +940,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) subtraction*/ static PyObject *Vector_isub(PyObject * v1, PyObject * v2) { - int i; - VectorObject *vec1 = NULL, *vec2 = NULL; + VectorObject *vec1= NULL, *vec2= NULL; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation"); @@ -975,12 +957,10 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; - for(i = 0; i < vec1->size; i++) { - vec1->vec[i] = vec1->vec[i] - vec2->vec[i]; - } + sub_vn_vn(vec1->vec, vec2->vec, vec1->size); (void)BaseMath_WriteCallback(vec1); - Py_INCREF( v1 ); + Py_INCREF(v1); return v1; } @@ -996,29 +976,29 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2) * 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) +static int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec, MatrixObject * mat) { - float vecCopy[4]; + float vec_cpy[MAX_DIMENSIONS]; 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"); + if(mat->rowSize == 4 && vec->size == 3) { + vec_cpy[3] = 1.0f; + } + else { + PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix.row_size and len(vector) must be the same, except for 3D vector * 4x4 matrix."); return -1; - }else{ - vecCopy[3] = 1.0f; } } - for(x = 0; x < vec->size; x++){ - vecCopy[x] = vec->vec[x]; - } + memcpy(vec_cpy, vec->vec, vec->size * sizeof(float)); + 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]; + dot += mat->matrix[y][x] * vec_cpy[y]; } rvec[z++] = (float)dot; dot = 0.0f; @@ -1030,11 +1010,7 @@ static int column_vector_multiplication(float *rvec, VectorObject* vec, MatrixOb static PyObject *vector_mul_float(VectorObject *vec, const float scalar) { float tvec[MAX_DIMENSIONS]; - int i; - - for(i = 0; i < vec->size; i++) { - tvec[i] = vec->vec[i] * scalar; - } + mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar); return newVectorObject(tvec, vec->size, Py_NEW, Py_TYPE(vec)); } @@ -1493,7 +1469,7 @@ static PyObject *Vector_getLength(VectorObject *self, void *UNUSED(closure)) return PyFloat_FromDouble(sqrt(dot)); } -static int Vector_setLength(VectorObject *self, PyObject * value ) +static int Vector_setLength(VectorObject *self, PyObject *value) { double dot = 0.0f, param; int i; @@ -1511,9 +1487,7 @@ static int Vector_setLength(VectorObject *self, PyObject * value ) return -1; } if (param == 0.0f) { - for(i = 0; i < self->size; i++){ - self->vec[i]= 0; - } + fill_vn(self->vec, self->size, 0.0f); return 0; } @@ -2052,7 +2026,7 @@ if len(unique) != len(items): //vector/matrix multiplication IS NOT COMMUTATIVE!!!! static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObject * mat) { - float vecCopy[4]; + float vec_cpy[4]; double dot = 0.0f; int x, y, z = 0, vec_size = vec->size; @@ -2061,21 +2035,20 @@ static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObj PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); return -1; }else{ - vecCopy[3] = 1.0f; + vec_cpy[3] = 1.0f; } } if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat)) return -1; - - for(x = 0; x < vec_size; x++){ - vecCopy[x] = vec->vec[x]; - } + + memcpy(vec_cpy, vec->vec, vec_size * sizeof(float)); + 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]; + dot += mat->matrix[x][y] * vec_cpy[y]; } rvec[z++] = (float)dot; dot = 0.0f; @@ -2226,9 +2199,8 @@ PyTypeObject vector_Type = { (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type) +PyObject *newVectorObject(float *vec, const int size, const int type, PyTypeObject *base_type) { - int i; VectorObject *self; if(size > 4 || size < 2) @@ -2247,16 +2219,14 @@ PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_typ self->vec = vec; self->wrapped = Py_WRAP; } else if (type == Py_NEW) { - self->vec = PyMem_Malloc(size * sizeof(float)); - if(!vec) { /*new empty*/ - for(i = 0; i < size; i++){ - self->vec[i] = 0.0f; - } - if(size == 4) /* do the homogenous thing */ + self->vec= PyMem_Malloc(size * sizeof(float)); + if(vec) { + memcpy(self->vec, vec, size * sizeof(float)); + } + else { /* new empty */ + fill_vn(self->vec, size, 0.0f); + if(size == 4) { /* do the homogenous thing */ self->vec[3] = 1.0f; - }else{ - for(i = 0; i < size; i++){ - self->vec[i] = vec[i]; } } self->wrapped = Py_NEW; diff --git a/source/blender/python/generic/mathutils_vector.h b/source/blender/python/generic/mathutils_vector.h index e5d15dbfdb0..2dbe9d9d3fe 100644 --- a/source/blender/python/generic/mathutils_vector.h +++ b/source/blender/python/generic/mathutils_vector.h @@ -43,7 +43,7 @@ typedef struct { } VectorObject; /*prototypes*/ -PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type); +PyObject *newVectorObject(float *vec, const int size, const int type, PyTypeObject *base_type); PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype); #endif /* MATHUTILS_VECTOR_H */ |