21a5ceaa3b23af3f612a04f4d648f185f751dce9
[blender.git] / source / blender / freestyle / intern / python / BPy_FrsNoise.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
22  *  \ingroup freestyle
23  */
24
25 #include "BPy_FrsNoise.h"
26 #include "BPy_Convert.h"
27
28 #include "../system/RandGen.h"
29
30 #include <sstream>
31
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35
36 ///////////////////////////////////////////////////////////////////////////////////////////
37
38 //-------------------MODULE INITIALIZATION--------------------------------
39 int FrsNoise_Init(PyObject *module)
40 {
41         if (module == NULL)
42                 return -1;
43
44         if (PyType_Ready(&FrsNoise_Type) < 0)
45                 return -1;
46         Py_INCREF(&FrsNoise_Type);
47         PyModule_AddObject(module, "Noise", (PyObject *)&FrsNoise_Type);
48
49         return 0;
50 }
51
52 //------------------------INSTANCE METHODS ----------------------------------
53
54 PyDoc_STRVAR(FrsNoise_doc,
55 "Class to provide Perlin noise functionalities.\n"
56 "\n"
57 ".. method:: __init__(seed = -1)\n"
58 "\n"
59 "   Builds a Noise object.  Seed is an optional argument.  The seed value is used\n"
60 "   as a seed for random number generation if it is equal to or greater than zero;\n"
61 "   otherwise, time is used as a seed.\n"
62 "\n"
63 "   :arg seed: Seed for random number generation.\n"
64 "   :type seed: int");
65
66 static int FrsNoise_init(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
67 {
68         static const char *kwlist[] = {"seed", NULL};
69         long seed = -1;
70
71         if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", (char **)kwlist, &seed))
72                 return -1;
73         self->n = new Noise(seed);
74         self->pn = new PseudoNoise();
75         return 0;
76 }
77
78 static void FrsNoise_dealloc(BPy_FrsNoise *self)
79 {
80         delete self->n;
81         delete self->pn;
82         Py_TYPE(self)->tp_free((PyObject *)self);
83 }
84
85 static PyObject *FrsNoise_repr(BPy_FrsNoise *self)
86 {
87         return PyUnicode_FromFormat("Noise - address: %p", self->n);
88 }
89
90 PyDoc_STRVAR(FrsNoise_turbulence1_doc,
91 ".. method:: turbulence1(v, freq, amp, oct=4)\n"
92 "\n"
93 "   Returns a noise value for a 1D element.\n"
94 "\n"
95 "   :arg v: One-dimensional sample point.\n"
96 "   :type v: float\n"
97 "   :arg freq: Noise frequency.\n"
98 "   :type freq: float\n"
99 "   :arg amp: Amplitude.\n"
100 "   :type amp: float\n"
101 "   :arg oct: Number of octaves.\n"
102 "   :type oct: int\n"
103 "   :return: A noise value.\n"
104 "   :rtype: float");
105
106 static PyObject *FrsNoise_drand(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
107 {
108         static const char *kwlist[] = {"seed", NULL};
109         long seed = 0;
110         if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", (char **)kwlist, &seed)) {
111                 PyErr_SetString(PyExc_TypeError, "optional argument 1 must be of type int");
112                 return NULL;
113         }
114         if (seed){
115                 RandGen::srand48(seed);
116         }
117         return PyFloat_FromDouble(RandGen::drand48());
118 }
119
120 static PyObject *FrsNoise_turbulence_smooth(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
121 {
122         static const char *kwlist[] = {"v", "oct", NULL};
123
124         double x;  // note: this has to be a double (not float)
125         unsigned nbOctaves = 8;
126
127         if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|I", (char **)kwlist, &x, &nbOctaves))
128                 return NULL;
129         return PyFloat_FromDouble(self->pn->turbulenceSmooth(x, nbOctaves));
130 }
131
132 static PyObject *FrsNoise_turbulence1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
133 {
134         static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL};
135         float f1, f2, f3;
136         unsigned int i = 4;
137
138         if (!PyArg_ParseTupleAndKeywords(args, kwds, "fff|I", (char **)kwlist, &f1, &f2, &f3, &i))
139                 return NULL;
140         return PyFloat_FromDouble(self->n->turbulence1(f1, f2, f3, i));
141 }
142
143 PyDoc_STRVAR(FrsNoise_turbulence2_doc,
144 ".. method:: turbulence2(v, freq, amp, oct=4)\n"
145 "\n"
146 "   Returns a noise value for a 2D element.\n"
147 "\n"
148 "   :arg v: Two-dimensional sample point.\n"
149 "   :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
150 "   :arg freq: Noise frequency.\n"
151 "   :type freq: float\n"
152 "   :arg amp: Amplitude.\n"
153 "   :type amp: float\n"
154 "   :arg oct: Number of octaves.\n"
155 "   :type oct: int\n"
156 "   :return: A noise value.\n"
157 "   :rtype: float");
158
159 static PyObject *FrsNoise_turbulence2(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
160 {
161         static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL};
162         PyObject *obj1;
163         float f2, f3;
164         unsigned int i = 4;
165         Vec2f vec;
166
167         if (!PyArg_ParseTupleAndKeywords(args, kwds, "Off|I", (char **)kwlist, &obj1, &f2, &f3, &i))
168                 return NULL;
169         if (!Vec2f_ptr_from_PyObject(obj1, vec)) {
170                 PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
171                 return NULL;
172         }
173         float t = self->n->turbulence2(vec, f2, f3, i);
174         return PyFloat_FromDouble(t);
175 }
176
177 PyDoc_STRVAR(FrsNoise_turbulence3_doc,
178 ".. method:: turbulence3(v, freq, amp, oct=4)\n"
179 "\n"
180 "   Returns a noise value for a 3D element.\n"
181 "\n"
182 "   :arg v: Three-dimensional sample point.\n"
183 "   :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
184 "   :arg freq: Noise frequency.\n"
185 "   :type freq: float\n"
186 "   :arg amp: Amplitude.\n"
187 "   :type amp: float\n"
188 "   :arg oct: Number of octaves.\n"
189 "   :type oct: int\n"
190 "   :return: A noise value.\n"
191 "   :rtype: float");
192
193 static PyObject *FrsNoise_turbulence3(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
194 {
195         static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL};
196         PyObject *obj1;
197         float f2, f3;
198         unsigned int i = 4;
199         Vec3f vec;
200
201         if (!PyArg_ParseTupleAndKeywords(args, kwds, "Off|I", (char **)kwlist, &obj1, &f2, &f3, &i))
202                 return NULL;
203         if (!Vec3f_ptr_from_PyObject(obj1, vec)) {
204                 PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
205                 return NULL;
206         }
207         float t = self->n->turbulence3(vec, f2, f3, i);
208         return PyFloat_FromDouble(t);
209 }
210
211 PyDoc_STRVAR(FrsNoise_smoothNoise1_doc,
212 ".. method:: smoothNoise1(v)\n"
213 "\n"
214 "   Returns a smooth noise value for a 1D element.\n"
215 "\n"
216 "   :arg v: One-dimensional sample point.\n"
217 "   :type v: float\n"
218 "   :return: A smooth noise value.\n"
219 "   :rtype: float");
220
221 static PyObject *FrsNoise_smoothNoise1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
222 {
223         static const char *kwlist[] = {"v", NULL};
224         float f;
225
226         if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &f))
227                 return NULL;
228         return PyFloat_FromDouble(self->n->smoothNoise1(f));
229 }
230
231 PyDoc_STRVAR(FrsNoise_smoothNoise2_doc,
232 ".. method:: smoothNoise2(v)\n"
233 "\n"
234 "   Returns a smooth noise value for a 2D element.\n"
235 "\n"
236 "   :arg v: Two-dimensional sample point.\n"
237 "   :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
238 "   :return: A smooth noise value.\n"
239 "   :rtype: float");
240
241 static PyObject *FrsNoise_smoothNoise2(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
242 {
243         static const char *kwlist[] = {"v", NULL};
244         PyObject *obj;
245         Vec2f vec;
246
247         if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj))
248                 return NULL;
249         if (!Vec2f_ptr_from_PyObject(obj, vec)) {
250                 PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
251                 return NULL;
252         }
253         float t = self->n->smoothNoise2(vec);
254         return PyFloat_FromDouble(t);
255 }
256
257 PyDoc_STRVAR(FrsNoise_smoothNoise3_doc,
258 ".. method:: smoothNoise3(v)\n"
259 "\n"
260 "   Returns a smooth noise value for a 3D element.\n"
261 "\n"
262 "   :arg v: Three-dimensional sample point.\n"
263 "   :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
264 "   :return: A smooth noise value.\n"
265 "   :rtype: float");
266
267 static PyObject *FrsNoise_smoothNoise3(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
268 {
269         static const char *kwlist[] = {"v", NULL};
270         PyObject *obj;
271         Vec3f vec;
272
273         if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj))
274                 return NULL;
275         if (!Vec3f_ptr_from_PyObject(obj, vec)) {
276                 PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
277                 return NULL;
278         }
279         float t = self->n->smoothNoise3(vec);
280         return PyFloat_FromDouble(t);
281 }
282
283 static PyMethodDef BPy_FrsNoise_methods[] = {
284         {"turbulence1", (PyCFunction)FrsNoise_turbulence1, METH_VARARGS | METH_KEYWORDS, FrsNoise_turbulence1_doc},
285         {"turbulence2", (PyCFunction)FrsNoise_turbulence2, METH_VARARGS | METH_KEYWORDS, FrsNoise_turbulence2_doc},
286         {"turbulence3", (PyCFunction)FrsNoise_turbulence3, METH_VARARGS | METH_KEYWORDS, FrsNoise_turbulence3_doc},
287         {"smoothNoise1", (PyCFunction)FrsNoise_smoothNoise1, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise1_doc},
288         {"smoothNoise2", (PyCFunction)FrsNoise_smoothNoise2, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise2_doc},
289         {"smoothNoise3", (PyCFunction)FrsNoise_smoothNoise3, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise3_doc},
290         {"rand", (PyCFunction)FrsNoise_drand, METH_VARARGS | METH_KEYWORDS, NULL},
291         {"turbulence_smooth", (PyCFunction)FrsNoise_turbulence_smooth, METH_VARARGS | METH_KEYWORDS, NULL},
292         {NULL, NULL, 0, NULL}
293 };
294
295 /*-----------------------BPy_FrsNoise type definition ------------------------------*/
296
297 PyTypeObject FrsNoise_Type = {
298         PyVarObject_HEAD_INIT(NULL, 0)
299         "Noise",                        /* tp_name */
300         sizeof(BPy_FrsNoise),           /* tp_basicsize */
301         0,                              /* tp_itemsize */
302         (destructor)FrsNoise_dealloc,   /* tp_dealloc */
303         0,                              /* tp_print */
304         0,                              /* tp_getattr */
305         0,                              /* tp_setattr */
306         0,                              /* tp_reserved */
307         (reprfunc)FrsNoise_repr,        /* tp_repr */
308         0,                              /* tp_as_number */
309         0,                              /* tp_as_sequence */
310         0,                              /* tp_as_mapping */
311         0,                              /* tp_hash  */
312         0,                              /* tp_call */
313         0,                              /* tp_str */
314         0,                              /* tp_getattro */
315         0,                              /* tp_setattro */
316         0,                              /* tp_as_buffer */
317         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
318         FrsNoise_doc,                   /* tp_doc */
319         0,                              /* tp_traverse */
320         0,                              /* tp_clear */
321         0,                              /* tp_richcompare */
322         0,                              /* tp_weaklistoffset */
323         0,                              /* tp_iter */
324         0,                              /* tp_iternext */
325         BPy_FrsNoise_methods,           /* tp_methods */
326         0,                              /* tp_members */
327         0,                              /* tp_getset */
328         0,                              /* tp_base */
329         0,                              /* tp_dict */
330         0,                              /* tp_descr_get */
331         0,                              /* tp_descr_set */
332         0,                              /* tp_dictoffset */
333         (initproc)FrsNoise_init,        /* tp_init */
334         0,                              /* tp_alloc */
335         PyType_GenericNew,              /* tp_new */
336 };
337
338 ///////////////////////////////////////////////////////////////////////////////////////////
339
340 #ifdef __cplusplus
341 }
342 #endif