415 lines
14 KiB
C++
415 lines
14 KiB
C++
/******************************************************************************
|
|
*
|
|
* MantaFlow fluid solver framework
|
|
* Copyright 2011 Tobias Pfaff, Nils Thuerey
|
|
*
|
|
* This program is free software, distributed under the terms of the
|
|
* Apache License, Version 2.0
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Vec3 class extension for python
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include "pythonInclude.h"
|
|
#include <string>
|
|
#include <sstream>
|
|
#include "vectorbase.h"
|
|
#include "structmember.h"
|
|
#include "manta.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace Manta {
|
|
|
|
extern PyTypeObject PbVec3Type;
|
|
|
|
struct PbVec3 {
|
|
PyObject_HEAD float data[3];
|
|
};
|
|
|
|
static void PbVec3Dealloc(PbVec3 *self)
|
|
{
|
|
Py_TYPE(self)->tp_free((PyObject *)self);
|
|
}
|
|
|
|
static PyObject *PbVec3New(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
return type->tp_alloc(type, 0);
|
|
}
|
|
|
|
static int PbVec3Init(PbVec3 *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
|
|
float x1 = numeric_limits<float>::quiet_NaN(), x2 = x1, x3 = x1;
|
|
if (!PyArg_ParseTuple(args, "|fff", &x1, &x2, &x3))
|
|
return -1;
|
|
|
|
if (!c_isnan(x1)) {
|
|
self->data[0] = x1;
|
|
if (!c_isnan(x2) && !c_isnan(x3)) {
|
|
self->data[1] = x2;
|
|
self->data[2] = x3;
|
|
}
|
|
else {
|
|
if (!c_isnan(x2) || !c_isnan(x3)) {
|
|
errMsg("Invalid partial init of vec3");
|
|
}
|
|
self->data[1] = x1;
|
|
self->data[2] = x1;
|
|
}
|
|
}
|
|
else {
|
|
self->data[0] = 0;
|
|
self->data[1] = 0;
|
|
self->data[2] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *PbVec3Repr(PbVec3 *self)
|
|
{
|
|
Manta::Vec3 v(self->data[0], self->data[1], self->data[2]);
|
|
return PyUnicode_FromFormat(v.toString().c_str());
|
|
}
|
|
|
|
static PyMemberDef PbVec3Members[] = {
|
|
{(char *)"x", T_FLOAT, offsetof(PbVec3, data), 0, (char *)"X"},
|
|
{(char *)"y", T_FLOAT, offsetof(PbVec3, data) + sizeof(float), 0, (char *)"Y"},
|
|
{(char *)"z", T_FLOAT, offsetof(PbVec3, data) + sizeof(float) * 2, 0, (char *)"Z"},
|
|
{nullptr} // Sentinel
|
|
};
|
|
|
|
static PyMethodDef PbVec3Methods[] = {
|
|
//{"name", (PyCFunction)Noddy_name, METH_NOARGS, "Return the name, combining the first and last
|
|
//name" },
|
|
{nullptr} // Sentinel
|
|
};
|
|
|
|
// operator overloads
|
|
|
|
inline PyObject *PbNew(const Vec3 &a)
|
|
{
|
|
PbVec3 *obj = (PbVec3 *)PbVec3New(&PbVec3Type, 0, 0);
|
|
obj->data[0] = a.x;
|
|
obj->data[1] = a.y;
|
|
obj->data[2] = a.z;
|
|
return (PyObject *)obj;
|
|
}
|
|
|
|
#define CONVERTVEC(obj) \
|
|
Vec3 v##obj; \
|
|
if (PyObject_TypeCheck(obj, &PbVec3Type)) \
|
|
v##obj = Vec3(&(((PbVec3 *)obj)->data[0])); \
|
|
else if (PyFloat_Check(obj)) \
|
|
v##obj = Vec3(PyFloat_AsDouble(obj)); \
|
|
else if (PyLong_Check(obj)) \
|
|
v##obj = Vec3(PyLong_AsDouble(obj)); \
|
|
else { \
|
|
Py_INCREF(Py_NotImplemented); \
|
|
return Py_NotImplemented; \
|
|
}
|
|
|
|
#define OPHEADER \
|
|
if (!PyObject_TypeCheck(a, &PbVec3Type) && !PyObject_TypeCheck(b, &PbVec3Type)) { \
|
|
Py_INCREF(Py_NotImplemented); \
|
|
return Py_NotImplemented; \
|
|
} \
|
|
CONVERTVEC(a) \
|
|
CONVERTVEC(b)
|
|
|
|
#define OPHEADER1 \
|
|
if (!PyObject_TypeCheck(a, &PbVec3Type)) { \
|
|
Py_INCREF(Py_NotImplemented); \
|
|
return Py_NotImplemented; \
|
|
} \
|
|
CONVERTVEC(a)
|
|
|
|
PyObject *PbVec3Add(PyObject *a, PyObject *b)
|
|
{
|
|
OPHEADER
|
|
return PbNew(va + vb);
|
|
}
|
|
|
|
PyObject *PbVec3Sub(PyObject *a, PyObject *b)
|
|
{
|
|
OPHEADER
|
|
return PbNew(va - vb);
|
|
}
|
|
|
|
PyObject *PbVec3Mult(PyObject *a, PyObject *b)
|
|
{
|
|
OPHEADER
|
|
return PbNew(va * vb);
|
|
}
|
|
|
|
PyObject *PbVec3Div(PyObject *a, PyObject *b)
|
|
{
|
|
OPHEADER
|
|
return PbNew(va / vb);
|
|
}
|
|
|
|
PyObject *PbVec3Negative(PyObject *a)
|
|
{
|
|
OPHEADER1
|
|
return PbNew(-va);
|
|
}
|
|
|
|
// numbers are defined subtely different in Py3 (WTF?)
|
|
#if PY_MAJOR_VERSION >= 3
|
|
static PyNumberMethods PbVec3NumberMethods = {
|
|
(binaryfunc)PbVec3Add, // binaryfunc nb_add;
|
|
(binaryfunc)PbVec3Sub, // binaryfunc nb_sub;
|
|
(binaryfunc)PbVec3Mult, // binaryfunc nb_mult;
|
|
0, // binaryfunc nb_remainder;
|
|
0, // binaryfunc nb_divmod;
|
|
0, // ternaryfunc nb_power;
|
|
(unaryfunc)PbVec3Negative, // unaryfunc nb_negative;
|
|
0, // unaryfunc nb_positive;
|
|
0, // unaryfunc nb_absolute;
|
|
0, // inquiry nb_bool;
|
|
0, // unaryfunc nb_invert;
|
|
0, // binaryfunc nb_lshift;
|
|
0, // binaryfunc nb_rshift;
|
|
0, // binaryfunc nb_and;
|
|
0, // binaryfunc nb_xor;
|
|
0, // binaryfunc nb_or;
|
|
0, // unaryfunc nb_int;
|
|
0, // void *nb_reserved;
|
|
0, // unaryfunc nb_float;
|
|
0, // binaryfunc nb_inplace_add;
|
|
0, // binaryfunc nb_inplace_subtract;
|
|
0, // binaryfunc nb_inplace_multiply;
|
|
0, // binaryfunc nb_inplace_remainder;
|
|
0, // ternaryfunc nb_inplace_power;
|
|
0, // binaryfunc nb_inplace_lshift;
|
|
0, // binaryfunc nb_inplace_rshift;
|
|
0, // binaryfunc nb_inplace_and;
|
|
0, // binaryfunc nb_inplace_xor;
|
|
0, // binaryfunc nb_inplace_or;
|
|
|
|
0, // binaryfunc nb_floor_divide;
|
|
(binaryfunc)PbVec3Div, // binaryfunc nb_true_divide;
|
|
0, // binaryfunc nb_inplace_floor_divide;
|
|
0, // binaryfunc nb_inplace_true_divide;
|
|
|
|
0 // unaryfunc nb_index;
|
|
};
|
|
#else
|
|
static PyNumberMethods PbVec3NumberMethods = {
|
|
(binaryfunc)PbVec3Add, // binaryfunc nb_add;
|
|
(binaryfunc)PbVec3Sub, // binaryfunc nb_sub;
|
|
(binaryfunc)PbVec3Mult, // binaryfunc nb_mult;
|
|
0, // binaryfunc nb_divide;
|
|
0, // binaryfunc nb_remainder;
|
|
0, // binaryfunc nb_divmod;
|
|
0, // ternaryfunc nb_power;
|
|
(unaryfunc)PbVec3Negative, // unaryfunc nb_negative;
|
|
0, // unaryfunc nb_positive;
|
|
0, // unaryfunc nb_absolute;
|
|
0, // inquiry nb_nonzero;
|
|
0, // unaryfunc nb_invert;
|
|
0, // binaryfunc nb_lshift;
|
|
0, // binaryfunc nb_rshift;
|
|
0, // binaryfunc nb_and;
|
|
0, // binaryfunc nb_xor;
|
|
0, // binaryfunc nb_or;
|
|
0, // coercion nb_coerce;
|
|
0, // unaryfunc nb_int;
|
|
0, // unaryfunc nb_long;
|
|
0, // unaryfunc nb_float;
|
|
0, // unaryfunc nb_oct;
|
|
0, // unaryfunc nb_hex;
|
|
0, // binaryfunc nb_inplace_add;
|
|
0, // binaryfunc nb_inplace_subtract;
|
|
0, // binaryfunc nb_inplace_multiply;
|
|
0, // binaryfunc nb_inplace_divide;
|
|
0, // binaryfunc nb_inplace_remainder;
|
|
0, // ternaryfunc nb_inplace_power;
|
|
0, // binaryfunc nb_inplace_lshift;
|
|
0, // binaryfunc nb_inplace_rshift;
|
|
0, // binaryfunc nb_inplace_and;
|
|
0, // binaryfunc nb_inplace_xor;
|
|
0, // binaryfunc nb_inplace_or;
|
|
0, // binaryfunc nb_floor_divide;
|
|
(binaryfunc)PbVec3Div, // binaryfunc nb_true_divide;
|
|
0, // binaryfunc nb_inplace_floor_divide;
|
|
0, // binaryfunc nb_inplace_true_divide;
|
|
0, // unaryfunc nb_index;
|
|
};
|
|
#endif
|
|
|
|
PyTypeObject PbVec3Type = {
|
|
PyVarObject_HEAD_INIT(nullptr, 0) "manta.vec3", /* tp_name */
|
|
sizeof(PbVec3), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PbVec3Dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_reserved */
|
|
(reprfunc)PbVec3Repr, /* tp_repr */
|
|
&PbVec3NumberMethods, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
#if PY_MAJOR_VERSION >= 3
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
#else
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
|
|
#endif
|
|
"float vector type", /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PbVec3Methods, /* tp_methods */
|
|
PbVec3Members, /* tp_members */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PbVec3Init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PbVec3New, /* tp_new */
|
|
};
|
|
|
|
inline PyObject *castPy(PyTypeObject *p)
|
|
{
|
|
return reinterpret_cast<PyObject *>(static_cast<void *>(p));
|
|
}
|
|
|
|
// 4d vector
|
|
|
|
extern PyTypeObject PbVec4Type;
|
|
|
|
struct PbVec4 {
|
|
PyObject_HEAD float data[4];
|
|
};
|
|
|
|
static PyMethodDef PbVec4Methods[] = {
|
|
{nullptr} // Sentinel
|
|
};
|
|
|
|
static PyMemberDef PbVec4Members[] = {
|
|
{(char *)"x", T_FLOAT, offsetof(PbVec4, data), 0, (char *)"X"},
|
|
{(char *)"y", T_FLOAT, offsetof(PbVec4, data) + sizeof(float) * 1, 0, (char *)"Y"},
|
|
{(char *)"z", T_FLOAT, offsetof(PbVec4, data) + sizeof(float) * 2, 0, (char *)"Z"},
|
|
{(char *)"t", T_FLOAT, offsetof(PbVec4, data) + sizeof(float) * 3, 0, (char *)"T"},
|
|
{nullptr} // Sentinel
|
|
};
|
|
|
|
static void PbVec4Dealloc(PbVec4 *self)
|
|
{
|
|
Py_TYPE(self)->tp_free((PyObject *)self);
|
|
}
|
|
|
|
static PyObject *PbVec4New(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
return type->tp_alloc(type, 0);
|
|
}
|
|
|
|
static int PbVec4Init(PbVec4 *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
|
|
float x1 = numeric_limits<float>::quiet_NaN(), x2 = x1, x3 = x1, x4 = x1;
|
|
if (!PyArg_ParseTuple(args, "|ffff", &x1, &x2, &x3, &x4))
|
|
return -1;
|
|
|
|
if (!c_isnan(x1)) {
|
|
self->data[0] = x1;
|
|
if (!c_isnan(x2) && !c_isnan(x3) && !c_isnan(x4)) {
|
|
self->data[1] = x2;
|
|
self->data[2] = x3;
|
|
self->data[3] = x4;
|
|
}
|
|
else {
|
|
if (!c_isnan(x2) || !c_isnan(x3) || !c_isnan(x4)) {
|
|
errMsg("Invalid partial init of vec4");
|
|
}
|
|
self->data[1] = self->data[2] = self->data[3] = x1;
|
|
}
|
|
}
|
|
else {
|
|
self->data[0] = self->data[1] = self->data[2] = self->data[3] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *PbVec4Repr(PbVec4 *self)
|
|
{
|
|
Manta::Vec4 v(self->data[0], self->data[1], self->data[2], self->data[3]);
|
|
return PyUnicode_FromFormat(v.toString().c_str());
|
|
}
|
|
|
|
PyTypeObject PbVec4Type = {
|
|
PyVarObject_HEAD_INIT(nullptr, 0) "manta.vec4", /* tp_name */
|
|
sizeof(PbVec4), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PbVec4Dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_reserved */
|
|
(reprfunc)PbVec4Repr, /* tp_repr */
|
|
nullptr, // &PbVec4NumberMethods, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
#if PY_MAJOR_VERSION >= 3
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
#else
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
|
|
#endif
|
|
"float vector type", /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PbVec4Methods, /* tp_methods */
|
|
PbVec4Members, /* tp_members */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PbVec4Init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PbVec4New, /* tp_new */
|
|
};
|
|
|
|
// register
|
|
|
|
void PbVecInitialize(PyObject *module)
|
|
{
|
|
if (PyType_Ready(&PbVec3Type) < 0)
|
|
errMsg("can't initialize Vec3 type");
|
|
Py_INCREF(castPy(&PbVec3Type));
|
|
PyModule_AddObject(module, "vec3", (PyObject *)&PbVec3Type);
|
|
|
|
if (PyType_Ready(&PbVec4Type) < 0)
|
|
errMsg("can't initialize Vec4 type");
|
|
Py_INCREF(castPy(&PbVec4Type));
|
|
PyModule_AddObject(module, "vec4", (PyObject *)&PbVec4Type);
|
|
}
|
|
const static Pb::Register _REG(PbVecInitialize);
|
|
|
|
} // namespace Manta
|