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:
Diffstat (limited to 'source/blender/python/mathutils')
-rw-r--r--source/blender/python/mathutils/CMakeLists.txt1
-rw-r--r--source/blender/python/mathutils/mathutils.c5
-rw-r--r--source/blender/python/mathutils/mathutils.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c187
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c135
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c164
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c95
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c565
-rw-r--r--source/blender/python/mathutils/mathutils_noise.h2
9 files changed, 839 insertions, 317 deletions
diff --git a/source/blender/python/mathutils/CMakeLists.txt b/source/blender/python/mathutils/CMakeLists.txt
index adf7c85d7c9..811cc1acbab 100644
--- a/source/blender/python/mathutils/CMakeLists.txt
+++ b/source/blender/python/mathutils/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenlib
../../blenkernel
../../bmesh
+ ../../depsgraph
../../makesdna
../../../../intern/guardedalloc
)
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 566bac9cb09..07905d2be89 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -645,30 +645,25 @@ PyMODINIT_FUNC PyInit_mathutils(void)
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate()));
/* XXX, python doesnt do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
#ifndef MATH_STANDALONE
/* Noise submodule */
PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
/* BVHTree submodule */
PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
/* KDTree submodule */
PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
#endif
mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb);
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index 286dd9f0750..ab78009ff89 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -62,7 +62,7 @@ enum {
float *_data; /* array of data (alias), wrapped status depends on wrapped status */ \
PyObject *cb_user; /* if this vector references another object, otherwise NULL, \
* *Note* this owns its reference */ \
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ \
+ unsigned char cb_type; /* which user funcs do we adhere to, RNA, etc */ \
unsigned char cb_subtype; /* subtype: location, rotation... \
* to avoid defining many new functions for every attribute of the same type */ \
unsigned char flag /* wrapped data type? */ \
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index d4f9e5e80e2..c033a990901 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -2321,7 +2321,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
- * multiplication */
+ * element-wise multiplication */
static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
@@ -2332,7 +2332,6 @@ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
{
float scalar;
- int vec_size;
MatrixObject *mat1 = NULL, *mat2 = NULL;
@@ -2348,9 +2347,118 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
}
if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
/* MATRIX * MATRIX */
float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+
+ return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
+#endif
+ }
+ else if (mat2) {
+ /*FLOAT/INT * MATRIX */
+ if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat2, scalar);
+ }
+ }
+ else if (mat1) {
+ /* MATRIX * FLOAT/INT */
+ if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * Inplace element-wise multiplication */
+static PyObject *Matrix_imul(PyObject *m1, PyObject *m2)
+{
+ float scalar;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
+ /* MATRIX *= MATRIX */
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 *= matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* MATRIX *= FLOAT/INT */
+ mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
+}
+/*------------------------obj @ obj------------------------------
+ * matrix multiplication */
+static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
+{
+ int vec_size;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @ MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+
int col, row, item;
if (mat1->num_col != mat2->num_row) {
@@ -2372,14 +2480,8 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
}
- else if (mat2) {
- /*FLOAT/INT * MATRIX */
- if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat2, scalar);
- }
- }
else if (mat1) {
- /* MATRIX * VECTOR */
+ /* MATRIX @ VECTOR */
if (VectorObject_Check(m2)) {
VectorObject *vec2 = (VectorObject *)m2;
float tvec[MATRIX_MAX_DIM];
@@ -2398,13 +2500,6 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2));
}
- /*FLOAT/INT * MATRIX */
- else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat1, scalar);
- }
- }
- else {
- BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
@@ -2413,6 +2508,62 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
return NULL;
}
+/*------------------------obj @= obj------------------------------
+ * inplace matrix multiplication */
+static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2)
+{
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @= MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ int col, row, item;
+
+ if (mat1->num_col != mat2->num_row) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of columns "
+ "and the matrix2 number of rows must be the same");
+ return NULL;
+ }
+
+ for (col = 0; col < mat2->num_col; col++) {
+ for (row = 0; row < mat1->num_row; row++) {
+ double dot = 0.0f;
+ for (item = 0; item < mat1->num_col; item++) {
+ dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
+ }
+ /* store in new matrix as overwriting original at this point will cause
+ * subsequent iterations to use incorrect values */
+ mat[(col * mat1->num_row) + row] = (float)dot;
+ }
+ }
+
+ /* copy matrix back */
+ memcpy(mat1->matrix, mat, (mat1->num_row * mat1->num_col) * sizeof(float));
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace matrix multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
+}
/*-----------------PROTOCOL DECLARATIONS--------------------------*/
static PySequenceMethods Matrix_SeqMethods = {
@@ -2527,7 +2678,7 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Matrix_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -2540,6 +2691,8 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Matrix_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Matrix_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Matrix_translation_doc,
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 645fa96c22e..a2b4480584a 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -834,7 +834,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
* multiplication */
static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
{
- float quat[QUAT_SIZE], scalar;
+ float scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if (QuaternionObject_Check(q1)) {
@@ -848,9 +848,12 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return NULL;
}
- if (quat1 && quat2) { /* QUAT * QUAT (cross product) */
- mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ if (quat1 && quat2) { /* QUAT * QUAT (element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ float quat[QUAT_SIZE];
+ mul_vn_vnvn(quat, quat1->quat, quat2->quat, QUAT_SIZE);
return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+#endif
}
/* the only case this can happen (for a supported type is "FLOAT * QUAT") */
else if (quat2) { /* FLOAT * QUAT */
@@ -858,8 +861,87 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return quat_mul_float(quat2, scalar);
}
}
+ else if (quat1) { /* QUAT * FLOAT */
+ if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ return quat_mul_float(quat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * inplace multiplication */
+static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2)
+{
+ float scalar;
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT *= QUAT (inplace element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ mul_vn_vn(quat1->quat, quat2->quat, QUAT_SIZE);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (quat1 && (((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* QUAT *= FLOAT */
+ mul_qt_fl(quat1->quat, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
+/*------------------------obj @ obj------------------------------
+ * quaternion multiplication */
+static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+ }
else if (quat1) {
- /* QUAT * VEC */
+ /* QUAT @ VEC */
if (VectorObject_Check(q2)) {
VectorObject *vec2 = (VectorObject *)q2;
float tvec[3];
@@ -880,13 +962,6 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2));
}
- /* QUAT * FLOAT */
- else if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
- return quat_mul_float(quat1, scalar);
- }
- }
- else {
- BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
@@ -895,6 +970,40 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
return NULL;
}
+/*------------------------obj @= obj------------------------------
+ * inplace quaternion multiplication */
+static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ copy_qt_qt(quat1->quat, quat);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace quaternion multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
/* -obj
* returns the negative of this object*/
@@ -952,7 +1061,7 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Quaternion_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -965,6 +1074,8 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Quaternion_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Quaternion_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Quaternion_axis_doc,
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index e7776f836aa..16a242fc718 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1706,12 +1706,25 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
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)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- int vec_size;
if (VectorObject_Check(v1)) {
vec1 = (VectorObject *)v1;
@@ -1729,6 +1742,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* 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: "
@@ -1736,30 +1750,12 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return NULL;
}
- /*dot product*/
- return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ /* element-wise product */
+ return vector_mul_vec(vec1, vec2);
+#endif
}
else if (vec1) {
- if (MatrixObject_Check(v2)) {
- /* VEC * MATRIX */
- float tvec[MAX_DIMENSIONS];
-
- if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
- return NULL;
- if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
- return NULL;
- }
-
- if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
- vec_size = 3;
- }
- else {
- vec_size = ((MatrixObject *)v2)->num_col;
- }
-
- return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
- }
- else if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
+ if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
return vector_mul_float(vec1, scalar);
}
}
@@ -1768,12 +1764,9 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return vector_mul_float(vec2, scalar);
}
}
- else {
- BLI_assert(!"internal error");
- }
PyErr_Format(PyExc_TypeError,
- "Vector multiplication: "
+ "Element-wise multiplication: "
"not supported between '%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
@@ -1782,32 +1775,129 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* multiplication in-place: obj *= obj */
static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
{
- VectorObject *vec = (VectorObject *)v1;
+ VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- if (BaseMath_ReadCallback_ForWrite(vec) == -1)
+ 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. */
- /* 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);
+ 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,
- "Vector multiplication: (%s *= %s) "
- "invalid type for this operation",
+ "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(vec);
+ (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;
+
+ 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) {
+ if (vec1->size != vec2->size) {
+ PyErr_SetString(PyExc_ValueError,
+ "Vector multiplication: "
+ "vectors must have the same dimensions for this operation");
+ return NULL;
+ }
+
+ /*dot product*/
+ return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ }
+ else if (vec1) {
+ if (MatrixObject_Check(v2)) {
+ /* VEC @ MATRIX */
+ float tvec[MAX_DIMENSIONS];
+
+ if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
+ return NULL;
+ if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
+ return NULL;
+ }
+
+ if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
+ vec_size = 3;
+ }
+ else {
+ vec_size = ((MatrixObject *)v2)->num_col;
+ }
+
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Vector multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+}
+
+static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
+{
+ PyErr_Format(PyExc_TypeError,
+ "Inplace vector multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+}
+
/* divid: obj / obj */
static PyObject *Vector_div(PyObject *v1, PyObject *v2)
{
@@ -2119,6 +2209,8 @@ static PyNumberMethods Vector_NumMethods = {
NULL, /* nb_inplace_floor_divide */
Vector_idiv, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Vector_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Vector_imatmul, /* nb_inplace_matrix_multiply */
};
/*------------------PY_OBECT DEFINITION--------------------------*/
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 36727fb91ae..fce0dd7d2af 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -48,10 +48,16 @@
#ifndef MATH_STANDALONE
#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_editmesh_bvh.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+
+#include "DEG_depsgraph_query.h"
#include "bmesh.h"
@@ -1045,88 +1051,98 @@ static PyObject *C_BVHTree_FromBMesh(PyObject *UNUSED(cls), PyObject *args, PyOb
}
/* return various derived meshes based on requested settings */
-static DerivedMesh *bvh_get_derived_mesh(
- const char *funcname, struct Scene *scene, Object *ob,
- bool use_deform, bool use_render, bool use_cage)
+static Mesh *bvh_get_mesh(
+ const char *funcname, struct Depsgraph *depsgraph, struct Scene *scene, Object *ob,
+ const bool use_deform, const bool use_cage, bool *r_free_mesh)
{
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
/* we only need minimum mesh data for topology and vertex locations */
CustomDataMask mask = CD_MASK_BAREMESH;
+ const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
+ *r_free_mesh = false;
/* Write the display mesh into the dummy mesh */
if (use_deform) {
if (use_render) {
if (use_cage) {
PyErr_Format(PyExc_ValueError,
- "%s(...): cage arg is unsupported when (render=True)", funcname);
+ "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", funcname);
return NULL;
}
else {
- return mesh_create_derived_render(scene, ob, mask);
+ *r_free_mesh = true;
+ return mesh_create_eval_final_render(depsgraph, scene, ob, mask);
}
}
- else {
+ else if (ob_eval != NULL) {
if (use_cage) {
- return mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */
+ return mesh_get_eval_deform(depsgraph, scene, ob_eval, mask); /* ob->derivedDeform */
}
else {
- return mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */
+ return mesh_get_eval_final(depsgraph, scene, ob_eval, mask); /* ob->derivedFinal */
}
}
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "%s(...): Cannot get evaluated data from given dependency graph / object pair", funcname);
+ return NULL;
+ }
}
else {
/* !use_deform */
if (use_render) {
if (use_cage) {
PyErr_Format(PyExc_ValueError,
- "%s(...): cage arg is unsupported when (render=True)", funcname);
+ "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", funcname);
return NULL;
}
else {
- return mesh_create_derived_no_deform_render(scene, ob, NULL, mask);
+ *r_free_mesh = true;
+ return mesh_create_eval_no_deform_render(depsgraph, scene, ob, NULL, mask);
}
}
else {
if (use_cage) {
PyErr_Format(PyExc_ValueError,
- "%s(...): cage arg is unsupported when (deform=False, render=False)", funcname);
+ "%s(...): cage arg is unsupported when deform=False and dependency graph evaluation mode is not RENDER", funcname);
return NULL;
}
else {
- return mesh_create_derived_no_deform(scene, ob, NULL, mask);
+ *r_free_mesh = true;
+ return mesh_create_eval_no_deform(depsgraph, scene, ob, NULL, mask);
}
}
}
}
PyDoc_STRVAR(C_BVHTree_FromObject_doc,
-".. classmethod:: FromObject(object, scene, deform=True, render=False, cage=False, epsilon=0.0)\n"
+".. classmethod:: FromObject(object, depsgraph, deform=True, render=False, cage=False, epsilon=0.0)\n"
"\n"
" BVH tree based on :class:`Object` data.\n"
"\n"
" :arg object: Object data.\n"
" :type object: :class:`Object`\n"
-" :arg scene: Scene data to use for evaluating the mesh.\n"
-" :type scene: :class:`Scene`\n"
+" :arg depsgraph: Depsgraph to use for evaluating the mesh.\n"
+" :type depsgraph: :class:`Depsgraph`\n"
" :arg deform: Use mesh with deformations.\n"
" :type deform: bool\n"
-" :arg render: Use render settings.\n"
-" :type render: bool\n"
-" :arg cage: Use render settings.\n"
+" :arg cage: Use modifiers cage.\n"
" :type cage: bool\n"
PYBVH_FROM_GENERIC_EPSILON_DOC
);
static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs)
{
/* note, options here match 'bpy_bmesh_from_object' */
- const char *keywords[] = {"object", "scene", "deform", "render", "cage", "epsilon", NULL};
+ const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", NULL};
- PyObject *py_ob, *py_scene;
+ PyObject *py_ob, *py_depsgraph;
Object *ob;
+ struct Depsgraph *depsgraph;
struct Scene *scene;
- DerivedMesh *dm;
+ Mesh *mesh;
bool use_deform = true;
- bool use_render = false;
bool use_cage = false;
+ bool free_mesh = false;
const MLoopTri *lt;
const MLoop *mloop;
@@ -1137,36 +1153,40 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO
float epsilon = 0.0f;
if (!PyArg_ParseTupleAndKeywords(
- args, kwargs, (char *)"OO|$O&O&O&f:BVHTree.FromObject", (char **)keywords,
- &py_ob, &py_scene,
+ args, kwargs, (char *)"OO|$O&O&f:BVHTree.FromObject", (char **)keywords,
+ &py_ob, &py_depsgraph,
PyC_ParseBool, &use_deform,
- PyC_ParseBool, &use_render,
PyC_ParseBool, &use_cage,
&epsilon) ||
((ob = PyC_RNA_AsPointer(py_ob, "Object")) == NULL) ||
- ((scene = PyC_RNA_AsPointer(py_scene, "Scene")) == NULL))
+ ((depsgraph = PyC_RNA_AsPointer(py_depsgraph, "Depsgraph")) == NULL))
{
return NULL;
}
- dm = bvh_get_derived_mesh("BVHTree", scene, ob, use_deform, use_render, use_cage);
- if (dm == NULL) {
+ scene = DEG_get_evaluated_scene(depsgraph);
+ mesh = bvh_get_mesh("BVHTree", depsgraph, scene, ob, use_deform, use_cage, &free_mesh);
+
+ if (mesh == NULL) {
return NULL;
}
/* Get data for tessellation */
{
- lt = dm->getLoopTriArray(dm);
+ lt = BKE_mesh_runtime_looptri_ensure(mesh);
- tris_len = (unsigned int)dm->getNumLoopTri(dm);
- coords_len = (unsigned int)dm->getNumVerts(dm);
+ tris_len = (unsigned int)BKE_mesh_runtime_looptri_len(mesh);
+ coords_len = (unsigned int)mesh->totvert;
coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__);
tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__);
- dm->getVertCos(dm, coords);
+ MVert *mv = mesh->mvert;
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ copy_v3_v3(coords[i], mv->co);
+ }
- mloop = dm->getLoopArray(dm);
+ mloop = mesh->mloop;
}
{
@@ -1179,7 +1199,8 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO
tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT);
if (tree) {
orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__);
- orig_normal = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
+ CustomData *pdata = &mesh->pdata;
+ orig_normal = CustomData_get_layer(pdata, CD_NORMAL); /* can be NULL */
if (orig_normal) {
orig_normal = MEM_dupallocN(orig_normal);
}
@@ -1202,7 +1223,9 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO
BLI_bvhtree_balance(tree);
}
- dm->release(dm);
+ if (free_mesh) {
+ BKE_id_free(NULL, mesh);
+ }
return bvhtree_CreatePyObject(
tree, epsilon,
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index 834322c0aed..5e3e86c8ddf 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -40,18 +40,11 @@
#include "DNA_texture_types.h"
+#include "../generic/py_capi_utils.h"
+
#include "mathutils.h"
#include "mathutils_noise.h"
-/* 2.6 update
- * Moved to submodule of mathutils.
- * All vector functions now return mathutils.Vector
- * Updated docs to be compatible with autodocs generation.
- * Updated vector functions to use nD array functions.
- * noise.vl_vector --> noise.variable_lacunarity
- * noise.vector --> noise.noise_vector
- */
-
/*-----------------------------------------*/
/* 'mersenne twister' random number generator */
@@ -198,6 +191,48 @@ static float frand(void)
/* Utility Functions */
/*------------------------------------------------------------*/
+#define BPY_NOISE_BASIS_ENUM_DOC \
+" :arg noise_basis: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \
+ "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \
+ "'CELLNOISE'].\n" \
+" :type noise_basis: string\n" \
+
+#define BPY_NOISE_METRIC_ENUM_DOC \
+" :arg distance_metric: Enumerator in ['DISTANCE', 'DISTANCE_SQUARED', 'MANHATTAN', 'CHEBYCHEV', " \
+ "'MINKOVSKY', 'MINKOVSKY_HALF', 'MINKOVSKY_FOUR'].\n" \
+" :type distance_metric: string\n" \
+
+/* Noise basis enum */
+#define DEFAULT_NOISE_TYPE TEX_STDPERLIN
+
+static PyC_FlagSet bpy_noise_types[] = {
+ {TEX_BLENDER, "BLENDER"},
+ {TEX_STDPERLIN, "PERLIN_ORIGINAL"},
+ {TEX_NEWPERLIN, "PERLIN_NEW"},
+ {TEX_VORONOI_F1, "VORONOI_F1"},
+ {TEX_VORONOI_F2, "VORONOI_F2"},
+ {TEX_VORONOI_F3, "VORONOI_F3"},
+ {TEX_VORONOI_F4, "VORONOI_F4"},
+ {TEX_VORONOI_F2F1, "VORONOI_F2F1"},
+ {TEX_VORONOI_CRACKLE, "VORONOI_CRACKLE"},
+ {TEX_CELLNOISE, "CELLNOISE"},
+ {0, NULL}
+};
+
+/* Metric basis enum */
+#define DEFAULT_METRIC_TYPE TEX_DISTANCE
+
+static PyC_FlagSet bpy_noise_metrics[] = {
+ {TEX_DISTANCE, "DISTANCE"},
+ {TEX_DISTANCE_SQUARED, "DISTANCE_SQUARED"},
+ {TEX_MANHATTAN, "MANHATTAN"},
+ {TEX_CHEBYCHEV, "CHEBYCHEV"},
+ {TEX_MINKOVSKY, "MINKOVSKY"},
+ {TEX_MINKOVSKY_HALF, "MINKOVSKY_HALF"},
+ {TEX_MINKOVSKY_FOUR, "MINKOVSKY_FOUR"},
+ {0, NULL}
+};
+
/* Fills an array of length size with random numbers in the range (-1, 1)*/
static void rand_vn(float *array_tar, const int size)
{
@@ -218,8 +253,9 @@ static void noise_vector(float x, float y, float z, int nb, float v[3])
}
/* Returns a turbulence value for a given position (x, y, z) */
-static float turb(float x, float y, float z, int oct, int hard, int nb,
- float ampscale, float freqscale)
+static float turb(
+ float x, float y, float z, int oct, int hard, int nb,
+ float ampscale, float freqscale)
{
float amp, out, t;
int i;
@@ -242,8 +278,9 @@ static float turb(float x, float y, float z, int oct, int hard, int nb,
/* Fills an array of length 3 with the turbulence vector for a given
* position (x, y, z) */
-static void vTurb(float x, float y, float z, int oct, int hard, int nb,
- float ampscale, float freqscale, float v[3])
+static void vTurb(
+ float x, float y, float z, int oct, int hard, int nb,
+ float ampscale, float freqscale, float v[3])
{
float amp, t[3];
int i;
@@ -283,7 +320,7 @@ PyDoc_STRVAR(M_Noise_doc,
PyDoc_STRVAR(M_Noise_random_doc,
".. function:: random()\n"
"\n"
-" Returns a random number in the range [0, 1].\n"
+" Returns a random number in the range [0, 1).\n"
"\n"
" :return: The random number.\n"
" :rtype: float\n"
@@ -298,71 +335,81 @@ PyDoc_STRVAR(M_Noise_random_unit_vector_doc,
"\n"
" Returns a unit vector with random entries.\n"
"\n"
-" :arg size: The size of the vector to be produced.\n"
-" :type size: Int\n"
+" :arg size: The size of the vector to be produced, in the range [2, 4].\n"
+" :type size: int\n"
" :return: The random unit vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"size", NULL};
float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float norm = 2.0f;
int size = 3;
- if (!PyArg_ParseTuple(args, "|i:random_vector", &size))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "|$i:random_unit_vector", (char **)kwlist,
+ &size))
+ {
return NULL;
+ }
if (size > 4 || size < 2) {
PyErr_SetString(PyExc_ValueError, "Vector(): invalid size");
return NULL;
}
- while (norm == 0.0f || norm >= 1.0f) {
+ while (norm == 0.0f || norm > 1.0f) {
rand_vn(vec, size);
norm = normalize_vn(vec, size);
}
return Vector_CreatePyObject(vec, size, NULL);
}
-/* This is dumb, most people will want a unit vector anyway, since this doesn't have uniform distribution over a sphere*/
-#if 0
+
PyDoc_STRVAR(M_Noise_random_vector_doc,
".. function:: random_vector(size=3)\n"
"\n"
-" Returns a vector with random entries in the range [0, 1).\n"
+" Returns a vector with random entries in the range (-1, 1).\n"
"\n"
" :arg size: The size of the vector to be produced.\n"
-" :type size: Int\n"
+" :type size: int\n"
" :return: The random vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
- float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ static const char *kwlist[] = {"size", NULL};
+ float *vec = NULL;
int size = 3;
- if (!PyArg_ParseTuple(args, "|i:random_vector", &size))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "|$i:random_vector", (char **)kwlist,
+ &size))
+ {
return NULL;
+ }
- if (size > 4 || size < 2) {
+ if (size < 2) {
PyErr_SetString(PyExc_ValueError, "Vector(): invalid size");
return NULL;
}
+ vec = PyMem_New(float, size);
+
rand_vn(vec, size);
- return Vector_CreatePyObject(vec, size, NULL);
+ return Vector_CreatePyObject_alloc(vec, size, NULL);
}
-#endif
PyDoc_STRVAR(M_Noise_seed_set_doc,
".. function:: seed_set(seed)\n"
"\n"
-" Sets the random seed used for random_unit_vector, random_vector and random.\n"
+" Sets the random seed used for random_unit_vector, and random.\n"
"\n"
" :arg seed: Seed used for the random generator.\n"
" When seed is zero, the current time will be used instead.\n"
-" :type seed: Int\n"
+" :type seed: int\n"
);
static PyObject *M_Noise_seed_set(PyObject *UNUSED(self), PyObject *args)
{
@@ -374,139 +421,198 @@ static PyObject *M_Noise_seed_set(PyObject *UNUSED(self), PyObject *args)
}
PyDoc_STRVAR(M_Noise_noise_doc,
-".. function:: noise(position, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: noise(position, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns noise value from the noise basis at the position specified.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_noise(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_noise(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "noise_basis", NULL};
PyObject *value;
float vec[3];
- int nb = 1;
- if (!PyArg_ParseTuple(args, "O|i:noise", &value, &nb))
+ const char *noise_basis_str = NULL;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|$s:noise", (char **)kwlist,
+ &value, &noise_basis_str))
+ {
+ return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "noise: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, vec[0], vec[1], vec[2], 0, nb) - 1.0f));
+ return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, vec[0], vec[1], vec[2], 0, noise_basis_enum) - 1.0f));
}
PyDoc_STRVAR(M_Noise_noise_vector_doc,
-".. function:: noise_vector(position, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: noise_vector(position, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns the noise vector from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The noise vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "noise_basis", NULL};
PyObject *value;
float vec[3], r_vec[3];
- int nb = 1;
+ const char *noise_basis_str = NULL;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "O|i:noise_vector", &value, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|$s:noise_vector", (char **)kwlist,
+ &value, &noise_basis_str))
+ {
+ return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise_vector") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "noise_vector: invalid 'position' arg") == -1)
return NULL;
- noise_vector(vec[0], vec[1], vec[2], nb, r_vec);
+ noise_vector(vec[0], vec[1], vec[2], noise_basis_enum, r_vec);
return Vector_CreatePyObject(r_vec, 3, NULL);
}
PyDoc_STRVAR(M_Noise_turbulence_doc,
-".. function:: turbulence(position, octaves, hard, noise_basis=noise.types.STDPERLIN, amplitude_scale=0.5, frequency_scale=2.0)\n"
+".. function:: turbulence(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)\n"
"\n"
" Returns the turbulence value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n"
-" :type hard: :boolean\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in mathutils.noise.types or int\n"
+" :type hard: boolean\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :arg amplitude_scale: The amplitude scaling factor.\n"
" :type amplitude_scale: float\n"
" :arg frequency_scale: The frequency scaling factor\n"
-" :type frequency_scale: Value in noise.types or int\n"
+" :type frequency_scale: float\n"
" :return: The turbulence value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_turbulence(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_turbulence(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL};
PyObject *value;
float vec[3];
- int oct, hd, nb = 1;
+ const char *noise_basis_str = NULL;
+ int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE;
float as = 0.5f, fs = 2.0f;
- if (!PyArg_ParseTuple(args, "Oii|iff:turbulence", &value, &oct, &hd, &nb, &as, &fs))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Oii|$sff:turbulence", (char **)kwlist,
+ &value, &oct, &hd, &noise_basis_str, &as, &fs))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "turbulence: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(turb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs));
+ return PyFloat_FromDouble(turb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs));
}
PyDoc_STRVAR(M_Noise_turbulence_vector_doc,
-".. function:: turbulence_vector(position, octaves, hard, noise_basis=noise.types.STDPERLIN, amplitude_scale=0.5, frequency_scale=2.0)\n"
+".. function:: turbulence_vector(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)\n"
"\n"
" Returns the turbulence vector from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n"
" :type hard: :boolean\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in mathutils.noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :arg amplitude_scale: The amplitude scaling factor.\n"
" :type amplitude_scale: float\n"
" :arg frequency_scale: The frequency scaling factor\n"
-" :type frequency_scale: Value in noise.types or int\n"
+" :type frequency_scale: float\n"
" :return: The turbulence vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL};
PyObject *value;
float vec[3], r_vec[3];
- int oct, hd, nb = 1;
+ const char *noise_basis_str = NULL;
+ int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE;
float as = 0.5f, fs = 2.0f;
- if (!PyArg_ParseTuple(args, "Oii|iff:turbulence_vector", &value, &oct, &hd, &nb, &as, &fs))
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Oii|$sff:turbulence_vector", (char **)kwlist,
+ &value, &oct, &hd, &noise_basis_str, &as, &fs))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence_vector") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "turbulence_vector: invalid 'position' arg") == -1)
return NULL;
- vTurb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs, r_vec);
+ vTurb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs, r_vec);
+
return Vector_CreatePyObject(r_vec, 3, NULL);
}
/* F. Kenton Musgrave's fractal functions */
PyDoc_STRVAR(M_Noise_fractal_doc,
-".. function:: fractal(position, H, lacunarity, octaves, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: fractal(position, H, lacunarity, octaves, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns the fractal Brownian motion (fBm) noise value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal increment factor.\n"
" :type H: float\n"
@@ -514,33 +620,47 @@ PyDoc_STRVAR(M_Noise_fractal_doc,
" :type lacunarity: float\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The fractal Brownian motion noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Offf|i:fractal", &value, &H, &lac, &oct, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offf|$s:fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &noise_basis_str))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "fractal") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_fBm(vec[0], vec[1], vec[2], H, lac, oct, nb));
+ return PyFloat_FromDouble(mg_fBm(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_multi_fractal_doc,
-".. function:: multi_fractal(position, H, lacunarity, octaves, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: multi_fractal(position, H, lacunarity, octaves, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns multifractal noise value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal increment factor.\n"
" :type H: float\n"
@@ -548,65 +668,107 @@ PyDoc_STRVAR(M_Noise_multi_fractal_doc,
" :type lacunarity: float\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The multifractal noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offf|$s:multi_fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &noise_basis_str))
+ {
+ return NULL;
+ }
- if (!PyArg_ParseTuple(args, "Offf|i:multi_fractal", &value, &H, &lac, &oct, &nb))
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "multi_fractal") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "multi_fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_MultiFractal(vec[0], vec[1], vec[2], H, lac, oct, nb));
+ return PyFloat_FromDouble(mg_MultiFractal(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_variable_lacunarity_doc,
-".. function:: variable_lacunarity(position, distortion, noise_type1=noise.types.STDPERLIN, noise_type2=noise.types.STDPERLIN)\n"
+".. function:: variable_lacunarity(position, distortion, noise_type1='PERLIN_ORIGINAL', noise_type2='PERLIN_ORIGINAL')\n"
"\n"
" Returns variable lacunarity noise value, a distorted variety of noise, from noise type 1 distorted by noise type 2 at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg distortion: The amount of distortion.\n"
" :type distortion: float\n"
-" :arg noise_type1: The type of noise to be distorted.\n"
-" :type noise_type1: Value in noise.types or int\n"
-" :arg noise_type2: The type of noise used to distort noise_type1.\n"
-" :type noise_type2: Value in noise.types or int\n"
+" :arg noise_type1: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \
+ "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \
+ "'CELLNOISE'].\n"
+" :type noise_type1: string\n"
+" :arg noise_type2: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \
+ "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \
+ "'CELLNOISE'].\n"
+" :type noise_type2: string\n"
" :return: The variable lacunarity noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_variable_lacunarity(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_variable_lacunarity(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "noise_type1", "noise_type2", NULL};
PyObject *value;
float vec[3];
+ const char *noise_type1_str = NULL, *noise_type2_str = NULL;
float d;
- int nt1 = 1, nt2 = 1;
+ int noise_type1_enum = DEFAULT_NOISE_TYPE, noise_type2_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Of|ii:variable_lacunarity", &value, &d, &nt1, &nt2))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Of|$ss:variable_lacunarity", (char **)kwlist,
+ &value, &d, &noise_type1_str, &noise_type2_str))
+ {
return NULL;
+ }
+
+ if (!noise_type1_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_type1_str, &noise_type1_enum, "variable_lacunarity") == -1)
+ {
+ return NULL;
+ }
+
+ if (!noise_type2_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_type2_str, &noise_type2_enum, "variable_lacunarity") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "variable_lacunarity: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_VLNoise(vec[0], vec[1], vec[2], d, nt1, nt2));
+ return PyFloat_FromDouble(mg_VLNoise(vec[0], vec[1], vec[2], d, noise_type1_enum, noise_type2_enum));
}
PyDoc_STRVAR(M_Noise_hetero_terrain_doc,
-".. function:: hetero_terrain(position, H, lacunarity, octaves, offset, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: hetero_terrain(position, H, lacunarity, octaves, offset, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns the heterogeneous terrain value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal dimension of the roughest areas.\n"
" :type H: float\n"
@@ -616,33 +778,47 @@ PyDoc_STRVAR(M_Noise_hetero_terrain_doc,
" :type octaves: int\n"
" :arg offset: The height of the terrain above 'sea level'.\n"
" :type offset: float\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The heterogeneous terrain value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct, ofs;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Offff|i:hetero_terrain", &value, &H, &lac, &oct, &ofs, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offff|$s:hetero_terrain", (char **)kwlist,
+ &value, &H, &lac, &oct, &ofs, &noise_basis_str))
+ {
+ return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "hetero_terrain") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "hetero_terrain: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_HeteroTerrain(vec[0], vec[1], vec[2], H, lac, oct, ofs, nb));
+ return PyFloat_FromDouble(mg_HeteroTerrain(vec[0], vec[1], vec[2], H, lac, oct, ofs, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_hybrid_multi_fractal_doc,
-".. function:: hybrid_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: hybrid_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns hybrid multifractal value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal dimension of the roughest areas.\n"
" :type H: float\n"
@@ -654,33 +830,47 @@ PyDoc_STRVAR(M_Noise_hybrid_multi_fractal_doc,
" :type offset: float\n"
" :arg gain: Scaling applied to the values.\n"
" :type gain: float\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The hybrid multifractal value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct, ofs, gn;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Offfff|i:hybrid_multi_fractal", &value, &H, &lac, &oct, &ofs, &gn, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offfff|$s:hybrid_multi_fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &ofs, &gn, &noise_basis_str))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "hybrid_multi_fractal") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "hybrid_multi_fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_HybridMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, nb));
+ return PyFloat_FromDouble(mg_HybridMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_ridged_multi_fractal_doc,
-".. function:: ridged_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: ridged_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns ridged multifractal value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal dimension of the roughest areas.\n"
" :type H: float\n"
@@ -692,67 +882,94 @@ PyDoc_STRVAR(M_Noise_ridged_multi_fractal_doc,
" :type offset: float\n"
" :arg gain: Scaling applied to the values.\n"
" :type gain: float\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The ridged multifractal value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct, ofs, gn;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offfff|$s:ridged_multi_fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &ofs, &gn, &noise_basis_str))
+ {
+ return NULL;
+ }
- if (!PyArg_ParseTuple(args, "Offfff|i:ridged_multi_fractal", &value, &H, &lac, &oct, &ofs, &gn, &nb))
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "ridged_multi_fractal") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "ridged_multi_fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_RidgedMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, nb));
+ return PyFloat_FromDouble(mg_RidgedMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_voronoi_doc,
-".. function:: voronoi(position, distance_metric=noise.distance_metrics.DISTANCE, exponent=2.5)\n"
+".. function:: voronoi(position, distance_metric='DISTANCE', exponent=2.5)\n"
"\n"
" Returns a list of distances to the four closest features and their locations.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
-" :arg distance_metric: Method of measuring distance.\n"
-" :type distance_metric: Value in noise.distance_metrics or int\n"
+BPY_NOISE_METRIC_ENUM_DOC
" :arg exponent: The exponent for Minkowski distance metric.\n"
" :type exponent: float\n"
" :return: A list of distances to the four closest features and their locations.\n"
" :rtype: list of four floats, list of four :class:`mathutils.Vector` types\n"
);
-static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "distance_metric", "exponent", NULL};
PyObject *value;
PyObject *list;
PyObject *ret;
float vec[3];
+ const char *metric_str = NULL;
float da[4], pa[12];
- int dtype = 0;
+ int metric_enum = DEFAULT_METRIC_TYPE;
float me = 2.5f; /* default minkowski exponent */
int i;
- if (!PyArg_ParseTuple(args, "O|if:voronoi", &value, &dtype, &me))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|$sf:voronoi", (char **)kwlist,
+ &value, &metric_str, &me))
+ {
return NULL;
+ }
+
+ if (!metric_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_metrics, metric_str, &metric_enum, "voronoi") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "voronoi: invalid 'position' arg") == -1)
return NULL;
list = PyList_New(4);
- voronoi(vec[0], vec[1], vec[2], da, pa, me, dtype);
+ voronoi(vec[0], vec[1], vec[2], da, pa, me, metric_enum);
for (i = 0; i < 4; i++) {
PyObject *v = Vector_CreatePyObject(pa + 3 * i, 3, NULL);
PyList_SET_ITEM(list, i, v);
- Py_DECREF(v);
}
ret = Py_BuildValue("[[ffff]O]", da[0], da[1], da[2], da[3], list);
@@ -765,7 +982,7 @@ PyDoc_STRVAR(M_Noise_cell_doc,
"\n"
" Returns cell noise value at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :return: The cell noise value.\n"
" :rtype: float\n"
@@ -789,7 +1006,7 @@ PyDoc_STRVAR(M_Noise_cell_vector_doc,
"\n"
" Returns cell noise vector at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :return: The cell noise vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
@@ -812,19 +1029,19 @@ static PyObject *M_Noise_cell_vector(PyObject *UNUSED(self), PyObject *args)
static PyMethodDef M_Noise_methods[] = {
{"seed_set", (PyCFunction) M_Noise_seed_set, METH_VARARGS, M_Noise_seed_set_doc},
{"random", (PyCFunction) M_Noise_random, METH_NOARGS, M_Noise_random_doc},
- {"random_unit_vector", (PyCFunction) M_Noise_random_unit_vector, METH_VARARGS, M_Noise_random_unit_vector_doc},
- /*{"random_vector", (PyCFunction) M_Noise_random_vector, METH_VARARGS, M_Noise_random_vector_doc},*/
- {"noise", (PyCFunction) M_Noise_noise, METH_VARARGS, M_Noise_noise_doc},
- {"noise_vector", (PyCFunction) M_Noise_noise_vector, METH_VARARGS, M_Noise_noise_vector_doc},
- {"turbulence", (PyCFunction) M_Noise_turbulence, METH_VARARGS, M_Noise_turbulence_doc},
- {"turbulence_vector", (PyCFunction) M_Noise_turbulence_vector, METH_VARARGS, M_Noise_turbulence_vector_doc},
- {"fractal", (PyCFunction) M_Noise_fractal, METH_VARARGS, M_Noise_fractal_doc},
- {"multi_fractal", (PyCFunction) M_Noise_multi_fractal, METH_VARARGS, M_Noise_multi_fractal_doc},
- {"variable_lacunarity", (PyCFunction) M_Noise_variable_lacunarity, METH_VARARGS, M_Noise_variable_lacunarity_doc},
- {"hetero_terrain", (PyCFunction) M_Noise_hetero_terrain, METH_VARARGS, M_Noise_hetero_terrain_doc},
- {"hybrid_multi_fractal", (PyCFunction) M_Noise_hybrid_multi_fractal, METH_VARARGS, M_Noise_hybrid_multi_fractal_doc},
- {"ridged_multi_fractal", (PyCFunction) M_Noise_ridged_multi_fractal, METH_VARARGS, M_Noise_ridged_multi_fractal_doc},
- {"voronoi", (PyCFunction) M_Noise_voronoi, METH_VARARGS, M_Noise_voronoi_doc},
+ {"random_unit_vector", (PyCFunction) M_Noise_random_unit_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_random_unit_vector_doc},
+ {"random_vector", (PyCFunction) M_Noise_random_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_random_vector_doc},
+ {"noise", (PyCFunction) M_Noise_noise, METH_VARARGS | METH_KEYWORDS, M_Noise_noise_doc},
+ {"noise_vector", (PyCFunction) M_Noise_noise_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_noise_vector_doc},
+ {"turbulence", (PyCFunction) M_Noise_turbulence, METH_VARARGS | METH_KEYWORDS, M_Noise_turbulence_doc},
+ {"turbulence_vector", (PyCFunction) M_Noise_turbulence_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_turbulence_vector_doc},
+ {"fractal", (PyCFunction) M_Noise_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_fractal_doc},
+ {"multi_fractal", (PyCFunction) M_Noise_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_multi_fractal_doc},
+ {"variable_lacunarity", (PyCFunction) M_Noise_variable_lacunarity, METH_VARARGS | METH_KEYWORDS, M_Noise_variable_lacunarity_doc},
+ {"hetero_terrain", (PyCFunction) M_Noise_hetero_terrain, METH_VARARGS | METH_KEYWORDS, M_Noise_hetero_terrain_doc},
+ {"hybrid_multi_fractal", (PyCFunction) M_Noise_hybrid_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_hybrid_multi_fractal_doc},
+ {"ridged_multi_fractal", (PyCFunction) M_Noise_ridged_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_ridged_multi_fractal_doc},
+ {"voronoi", (PyCFunction) M_Noise_voronoi, METH_VARARGS | METH_KEYWORDS, M_Noise_voronoi_doc},
{"cell", (PyCFunction) M_Noise_cell, METH_VARARGS, M_Noise_cell_doc},
{"cell_vector", (PyCFunction) M_Noise_cell_vector, METH_VARARGS, M_Noise_cell_vector_doc},
{NULL, NULL, 0, NULL}
@@ -845,78 +1062,10 @@ static struct PyModuleDef M_Noise_module_def = {
/*----------------------------MODULE INIT-------------------------*/
PyMODINIT_FUNC PyInit_mathutils_noise(void)
{
- PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *submodule = PyModule_Create(&M_Noise_module_def);
- PyObject *item_types, *item_metrics;
/* use current time as seed for random number generator by default */
setRndSeed(0);
- PyModule_AddObject(submodule, "types", (item_types = PyInit_mathutils_noise_types()));
- PyDict_SetItemString(sys_modules, "noise.types", item_types);
- Py_INCREF(item_types);
-
- PyModule_AddObject(submodule, "distance_metrics", (item_metrics = PyInit_mathutils_noise_metrics()));
- PyDict_SetItemString(sys_modules, "noise.distance_metrics", item_metrics);
- Py_INCREF(item_metrics);
-
- return submodule;
-}
-
-/*----------------------------SUBMODULE INIT-------------------------*/
-static struct PyModuleDef M_NoiseTypes_module_def = {
- PyModuleDef_HEAD_INIT,
- "mathutils.noise.types", /* m_name */
- NULL, /* m_doc */
- 0, /* m_size */
- NULL, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
-};
-
-PyMODINIT_FUNC PyInit_mathutils_noise_types(void)
-{
- PyObject *submodule = PyModule_Create(&M_NoiseTypes_module_def);
-
- PyModule_AddIntConstant(submodule, "BLENDER", TEX_BLENDER);
- PyModule_AddIntConstant(submodule, "STDPERLIN", TEX_STDPERLIN);
- PyModule_AddIntConstant(submodule, "NEWPERLIN", TEX_NEWPERLIN);
- PyModule_AddIntConstant(submodule, "VORONOI_F1", TEX_VORONOI_F1);
- PyModule_AddIntConstant(submodule, "VORONOI_F2", TEX_VORONOI_F2);
- PyModule_AddIntConstant(submodule, "VORONOI_F3", TEX_VORONOI_F3);
- PyModule_AddIntConstant(submodule, "VORONOI_F4", TEX_VORONOI_F4);
- PyModule_AddIntConstant(submodule, "VORONOI_F2F1", TEX_VORONOI_F2F1);
- PyModule_AddIntConstant(submodule, "VORONOI_CRACKLE", TEX_VORONOI_CRACKLE);
- PyModule_AddIntConstant(submodule, "CELLNOISE", TEX_CELLNOISE);
-
- return submodule;
-}
-
-static struct PyModuleDef M_NoiseMetrics_module_def = {
- PyModuleDef_HEAD_INIT,
- "mathutils.noise.distance_metrics", /* m_name */
- NULL, /* m_doc */
- 0, /* m_size */
- NULL, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
-};
-
-PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void)
-{
- PyObject *submodule = PyModule_Create(&M_NoiseMetrics_module_def);
-
- PyModule_AddIntConstant(submodule, "DISTANCE", TEX_DISTANCE);
- PyModule_AddIntConstant(submodule, "DISTANCE_SQUARED", TEX_DISTANCE_SQUARED);
- PyModule_AddIntConstant(submodule, "MANHATTAN", TEX_MANHATTAN);
- PyModule_AddIntConstant(submodule, "CHEBYCHEV", TEX_CHEBYCHEV);
- PyModule_AddIntConstant(submodule, "MINKOVSKY_HALF", TEX_MINKOVSKY_HALF);
- PyModule_AddIntConstant(submodule, "MINKOVSKY_FOUR", TEX_MINKOVSKY_FOUR);
- PyModule_AddIntConstant(submodule, "MINKOVSKY", TEX_MINKOVSKY);
-
return submodule;
}
diff --git a/source/blender/python/mathutils/mathutils_noise.h b/source/blender/python/mathutils/mathutils_noise.h
index f2218b28f8f..469cd9636e6 100644
--- a/source/blender/python/mathutils/mathutils_noise.h
+++ b/source/blender/python/mathutils/mathutils_noise.h
@@ -28,7 +28,5 @@
#define __MATHUTILS_NOISE_H__
PyMODINIT_FUNC PyInit_mathutils_noise(void);
-PyMODINIT_FUNC PyInit_mathutils_noise_types(void);
-PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void);
#endif /* __MATHUTILS_NOISE_H__ */