Changeset View
Changeset View
Standalone View
Standalone View
source/blender/python/mathutils/mathutils_Vector.c
| Show First 20 Lines • Show All 1,700 Lines • ▼ Show 20 Lines | PyErr_SetString(PyExc_MemoryError, | ||||
| "vec * float: " | "vec * float: " | ||||
| "problem allocating pointer space"); | "problem allocating pointer space"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar); | mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar); | ||||
| return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec)); | return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec)); | ||||
| } | } | ||||
| #ifdef USE_MATHUTILS_ELEM_MUL | |||||
| static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2) | |||||
| { | |||||
| float *tvec = PyMem_Malloc(vec1->size * sizeof(float)); | |||||
| if (tvec == NULL) { | |||||
| PyErr_SetString(PyExc_MemoryError, | |||||
| "vec * vec: " | |||||
| "problem allocating pointer space"); | |||||
| return NULL; | |||||
| } | |||||
| mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size); | |||||
| return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1)); | |||||
| } | |||||
| #endif | |||||
| static PyObject *Vector_mul(PyObject *v1, PyObject *v2) | static PyObject *Vector_mul(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | VectorObject *vec1 = NULL, *vec2 = NULL; | ||||
| float scalar; | float scalar; | ||||
| if (VectorObject_Check(v1)) { | |||||
| vec1 = (VectorObject *)v1; | |||||
| if (BaseMath_ReadCallback(vec1) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (VectorObject_Check(v2)) { | |||||
| vec2 = (VectorObject *)v2; | |||||
| if (BaseMath_ReadCallback(vec2) == -1) | |||||
| return NULL; | |||||
| } | |||||
| /* Intentionally don't support (Quaternion) here, uses reverse order instead. */ | |||||
| /* make sure v1 is always the vector */ | |||||
| if (vec1 && vec2) { | |||||
| #ifdef USE_MATHUTILS_ELEM_MUL | |||||
| if (vec1->size != vec2->size) { | |||||
| PyErr_SetString(PyExc_ValueError, | |||||
| "Vector multiplication: " | |||||
| "vectors must have the same dimensions for this operation"); | |||||
| return NULL; | |||||
| } | |||||
| /* element-wise product */ | |||||
| return vector_mul_vec(vec1, vec2); | |||||
| #endif | |||||
| } | |||||
| else if (vec1) { | |||||
| if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */ | |||||
| return vector_mul_float(vec1, scalar); | |||||
| } | |||||
| } | |||||
| else if (vec2) { | |||||
| if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * VEC */ | |||||
| return vector_mul_float(vec2, scalar); | |||||
| } | |||||
| } | |||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Element-wise multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| } | |||||
| /* multiplication in-place: obj *= obj */ | |||||
| static PyObject *Vector_imul(PyObject *v1, PyObject *v2) | |||||
| { | |||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | |||||
| float scalar; | |||||
| if (VectorObject_Check(v1)) { | |||||
| vec1 = (VectorObject *)v1; | |||||
| if (BaseMath_ReadCallback(vec1) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (VectorObject_Check(v2)) { | |||||
| vec2 = (VectorObject *)v2; | |||||
| if (BaseMath_ReadCallback(vec2) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (BaseMath_ReadCallback_ForWrite(vec1) == -1) | |||||
| return NULL; | |||||
| /* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */ | |||||
| if (vec1 && vec2) { | |||||
| #ifdef USE_MATHUTILS_ELEM_MUL | |||||
| if (vec1->size != vec2->size) { | |||||
| PyErr_SetString(PyExc_ValueError, | |||||
| "Vector multiplication: " | |||||
| "vectors must have the same dimensions for this operation"); | |||||
| return NULL; | |||||
| } | |||||
| /* element-wise product inplace */ | |||||
| mul_vn_vn(vec1->vec, vec2->vec, vec1->size); | |||||
| #else | |||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Inplace element-wise multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| #endif | |||||
| } | |||||
| else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) { /* VEC *= FLOAT */ | |||||
| mul_vn_fl(vec1->vec, vec1->size, scalar); | |||||
| } | |||||
| else { | |||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Inplace element-wise multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| } | |||||
| (void)BaseMath_WriteCallback(vec1); | |||||
| Py_INCREF(v1); | |||||
| return v1; | |||||
| } | |||||
| static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) | |||||
| { | |||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | |||||
| int vec_size; | int vec_size; | ||||
| if (VectorObject_Check(v1)) { | if (VectorObject_Check(v1)) { | ||||
| vec1 = (VectorObject *)v1; | vec1 = (VectorObject *)v1; | ||||
| if (BaseMath_ReadCallback(vec1) == -1) | if (BaseMath_ReadCallback(vec1) == -1) | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (VectorObject_Check(v2)) { | if (VectorObject_Check(v2)) { | ||||
| vec2 = (VectorObject *)v2; | vec2 = (VectorObject *)v2; | ||||
| if (BaseMath_ReadCallback(vec2) == -1) | if (BaseMath_ReadCallback(vec2) == -1) | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* Intentionally don't support (Quaternion) here, uses reverse order instead. */ | /* Intentionally don't support (Quaternion) here, uses reverse order instead. */ | ||||
| /* make sure v1 is always the vector */ | /* make sure v1 is always the vector */ | ||||
| if (vec1 && vec2) { | if (vec1 && vec2) { | ||||
| if (vec1->size != vec2->size) { | if (vec1->size != vec2->size) { | ||||
| PyErr_SetString(PyExc_ValueError, | PyErr_SetString(PyExc_ValueError, | ||||
| "Vector multiplication: " | "Vector multiplication: " | ||||
| "vectors must have the same dimensions for this operation"); | "vectors must have the same dimensions for this operation"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /*dot product*/ | /*dot product*/ | ||||
| return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size)); | return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size)); | ||||
| } | } | ||||
| else if (vec1) { | else if (vec1) { | ||||
| if (MatrixObject_Check(v2)) { | if (MatrixObject_Check(v2)) { | ||||
| /* VEC * MATRIX */ | /* VEC @ MATRIX */ | ||||
| float tvec[MAX_DIMENSIONS]; | float tvec[MAX_DIMENSIONS]; | ||||
| if (BaseMath_ReadCallback((MatrixObject *)v2) == -1) | if (BaseMath_ReadCallback((MatrixObject *)v2) == -1) | ||||
| return NULL; | return NULL; | ||||
| if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) { | if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) { | if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) { | ||||
| vec_size = 3; | vec_size = 3; | ||||
| } | } | ||||
| else { | else { | ||||
| vec_size = ((MatrixObject *)v2)->num_col; | vec_size = ((MatrixObject *)v2)->num_col; | ||||
| } | } | ||||
| return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1)); | return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1)); | ||||
| } | } | ||||
| else if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */ | |||||
| return vector_mul_float(vec1, scalar); | |||||
| } | |||||
| } | |||||
| else if (vec2) { | |||||
| if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * VEC */ | |||||
| return vector_mul_float(vec2, scalar); | |||||
| } | |||||
| } | |||||
| else { | |||||
| BLI_assert(!"internal error"); | |||||
| } | } | ||||
| PyErr_Format(PyExc_TypeError, | PyErr_Format(PyExc_TypeError, | ||||
| "Vector multiplication: " | "Vector multiplication: " | ||||
| "not supported between '%.200s' and '%.200s' types", | "not supported between '%.200s' and '%.200s' types", | ||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* multiplication in-place: obj *= obj */ | static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2) | ||||
| static PyObject *Vector_imul(PyObject *v1, PyObject *v2) | |||||
| { | { | ||||
| VectorObject *vec = (VectorObject *)v1; | |||||
| float scalar; | |||||
| if (BaseMath_ReadCallback_ForWrite(vec) == -1) | |||||
| return NULL; | |||||
| /* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */ | |||||
| /* only support 'vec *= float' | |||||
| * vec*=vec result is a float so that wont work */ | |||||
| if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC *= FLOAT */ | |||||
| mul_vn_fl(vec->vec, vec->size, scalar); | |||||
| } | |||||
| else { | |||||
| PyErr_Format(PyExc_TypeError, | PyErr_Format(PyExc_TypeError, | ||||
| "Vector multiplication: (%s *= %s) " | "Inplace vector multiplication: " | ||||
| "invalid type for this operation", | "not supported between '%.200s' and '%.200s' types", | ||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| (void)BaseMath_WriteCallback(vec); | |||||
| Py_INCREF(v1); | |||||
| return v1; | |||||
| } | |||||
| /* divid: obj / obj */ | /* divid: obj / obj */ | ||||
| static PyObject *Vector_div(PyObject *v1, PyObject *v2) | static PyObject *Vector_div(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| float *vec = NULL, scalar; | float *vec = NULL, scalar; | ||||
| VectorObject *vec1 = NULL; | VectorObject *vec1 = NULL; | ||||
| if (!VectorObject_Check(v1)) { /* not a vector */ | if (!VectorObject_Check(v1)) { /* not a vector */ | ||||
| PyErr_SetString(PyExc_TypeError, | PyErr_SetString(PyExc_TypeError, | ||||
| ▲ Show 20 Lines • Show All 295 Lines • ▼ Show 20 Lines | static PyNumberMethods Vector_NumMethods = { | ||||
| NULL, /* nb_inplace_and */ | NULL, /* nb_inplace_and */ | ||||
| NULL, /* nb_inplace_xor */ | NULL, /* nb_inplace_xor */ | ||||
| NULL, /* nb_inplace_or */ | NULL, /* nb_inplace_or */ | ||||
| NULL, /* nb_floor_divide */ | NULL, /* nb_floor_divide */ | ||||
| Vector_div, /* nb_true_divide */ | Vector_div, /* nb_true_divide */ | ||||
| NULL, /* nb_inplace_floor_divide */ | NULL, /* nb_inplace_floor_divide */ | ||||
| Vector_idiv, /* nb_inplace_true_divide */ | Vector_idiv, /* nb_inplace_true_divide */ | ||||
| NULL, /* nb_index */ | NULL, /* nb_index */ | ||||
| (binaryfunc) Vector_matmul, /* nb_matrix_multiply */ | |||||
| (binaryfunc) Vector_imatmul, /* nb_inplace_matrix_multiply */ | |||||
| }; | }; | ||||
| /*------------------PY_OBECT DEFINITION--------------------------*/ | /*------------------PY_OBECT DEFINITION--------------------------*/ | ||||
| /* vector axis, vector.x/y/z/w */ | /* vector axis, vector.x/y/z/w */ | ||||
| PyDoc_STRVAR(Vector_axis_x_doc, "Vector X axis.\n\n:type: float"); | PyDoc_STRVAR(Vector_axis_x_doc, "Vector X axis.\n\n:type: float"); | ||||
| PyDoc_STRVAR(Vector_axis_y_doc, "Vector Y axis.\n\n:type: float"); | PyDoc_STRVAR(Vector_axis_y_doc, "Vector Y axis.\n\n:type: float"); | ||||
| ▲ Show 20 Lines • Show All 962 Lines • Show Last 20 Lines | |||||