Add-ons may attempt to load the GPU module in background mode when no GPU
context has been initialized yet. This would give an error on import.
If then later the GPU context does get initialized, for example for a
render engine, import would still fail as the module is cached.
This reverts commit d7f124f06f, and again
throws errors in methods and constructors instead of module import.
Pull Request: https://projects.blender.org/blender/blender/pulls/123395
692 lines
18 KiB
C++
692 lines
18 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup bpygpu
|
|
*
|
|
* This file defines the gpu.matrix stack API.
|
|
*
|
|
* \warning While these functions attempt to ensure correct stack usage.
|
|
* Mixing Python and C functions may still crash on invalid use.
|
|
*
|
|
* - Use `bpygpu_` for local API.
|
|
* - Use `BPyGPU` for public API.
|
|
*/
|
|
|
|
#include <Python.h>
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "../mathutils/mathutils.h"
|
|
|
|
#include "../generic/py_capi_utils.h"
|
|
|
|
#define USE_GPU_PY_MATRIX_API
|
|
#include "GPU_matrix.hh"
|
|
#undef USE_GPU_PY_MATRIX_API
|
|
|
|
#include "gpu_py.hh"
|
|
#include "gpu_py_matrix.hh" /* own include */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Helper Functions
|
|
* \{ */
|
|
|
|
static bool pygpu_stack_is_push_model_view_ok_or_error()
|
|
{
|
|
if (GPU_matrix_stack_level_get_model_view() >= GPU_PY_MATRIX_STACK_LEN) {
|
|
PyErr_SetString(
|
|
PyExc_RuntimeError,
|
|
"Maximum model-view stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool pygpu_stack_is_push_projection_ok_or_error()
|
|
{
|
|
if (GPU_matrix_stack_level_get_projection() >= GPU_PY_MATRIX_STACK_LEN) {
|
|
PyErr_SetString(
|
|
PyExc_RuntimeError,
|
|
"Maximum projection stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool pygpu_stack_is_pop_model_view_ok_or_error()
|
|
{
|
|
if (GPU_matrix_stack_level_get_model_view() == 0) {
|
|
PyErr_SetString(PyExc_RuntimeError, "Minimum model-view stack depth reached");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool pygpu_stack_is_pop_projection_ok_or_error()
|
|
{
|
|
if (GPU_matrix_stack_level_get_projection() == 0) {
|
|
PyErr_SetString(PyExc_RuntimeError, "Minimum projection stack depth reached");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Manage Stack
|
|
* \{ */
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_push_doc,
|
|
".. function:: push()\n"
|
|
"\n"
|
|
" Add to the model-view matrix stack.\n");
|
|
static PyObject *pygpu_matrix_push(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
if (!pygpu_stack_is_push_model_view_ok_or_error()) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_push();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_pop_doc,
|
|
".. function:: pop()\n"
|
|
"\n"
|
|
" Remove the last model-view matrix from the stack.\n");
|
|
static PyObject *pygpu_matrix_pop(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
if (!pygpu_stack_is_pop_model_view_ok_or_error()) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_pop();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_push_projection_doc,
|
|
".. function:: push_projection()\n"
|
|
"\n"
|
|
" Add to the projection matrix stack.\n");
|
|
static PyObject *pygpu_matrix_push_projection(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
if (!pygpu_stack_is_push_projection_ok_or_error()) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_push_projection();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_pop_projection_doc,
|
|
".. function:: pop_projection()\n"
|
|
"\n"
|
|
" Remove the last projection matrix from the stack.\n");
|
|
static PyObject *pygpu_matrix_pop_projection(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
if (!pygpu_stack_is_pop_projection_ok_or_error()) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_pop_projection();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Stack (Context Manager)
|
|
*
|
|
* Safer alternative to ensure balanced push/pop calls.
|
|
*
|
|
* \{ */
|
|
|
|
struct BPyGPU_MatrixStackContext {
|
|
PyObject_HEAD /* Required Python macro. */
|
|
int type;
|
|
int level;
|
|
};
|
|
|
|
enum {
|
|
PYGPU_MATRIX_TYPE_MODEL_VIEW = 1,
|
|
PYGPU_MATRIX_TYPE_PROJECTION = 2,
|
|
};
|
|
|
|
static PyObject *pygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self);
|
|
static PyObject *pygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, PyObject *args);
|
|
|
|
#if (defined(__GNUC__) && !defined(__clang__))
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wcast-function-type"
|
|
#endif
|
|
|
|
static PyMethodDef pygpu_matrix_stack_context__tp_methods[] = {
|
|
{"__enter__", (PyCFunction)pygpu_matrix_stack_context_enter, METH_NOARGS},
|
|
{"__exit__", (PyCFunction)pygpu_matrix_stack_context_exit, METH_VARARGS},
|
|
{nullptr},
|
|
};
|
|
|
|
#if (defined(__GNUC__) && !defined(__clang__))
|
|
# pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
static PyTypeObject PyGPUMatrixStackContext_Type = {
|
|
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
|
|
/*tp_name*/ "GPUMatrixStackContext",
|
|
/*tp_basicsize*/ sizeof(BPyGPU_MatrixStackContext),
|
|
/*tp_itemsize*/ 0,
|
|
/*tp_dealloc*/ nullptr,
|
|
/*tp_vectorcall_offset*/ 0,
|
|
/*tp_getattr*/ nullptr,
|
|
/*tp_setattr*/ nullptr,
|
|
/*tp_as_async*/ nullptr,
|
|
/*tp_repr*/ nullptr,
|
|
/*tp_as_number*/ nullptr,
|
|
/*tp_as_sequence*/ nullptr,
|
|
/*tp_as_mapping*/ nullptr,
|
|
/*tp_hash*/ nullptr,
|
|
/*tp_call*/ nullptr,
|
|
/*tp_str*/ nullptr,
|
|
/*tp_getattro*/ nullptr,
|
|
/*tp_setattro*/ nullptr,
|
|
/*tp_as_buffer*/ nullptr,
|
|
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
|
|
/*tp_doc*/ nullptr,
|
|
/*tp_traverse*/ nullptr,
|
|
/*tp_clear*/ nullptr,
|
|
/*tp_richcompare*/ nullptr,
|
|
/*tp_weaklistoffset*/ 0,
|
|
/*tp_iter*/ nullptr,
|
|
/*tp_iternext*/ nullptr,
|
|
/*tp_methods*/ pygpu_matrix_stack_context__tp_methods,
|
|
/*tp_members*/ nullptr,
|
|
/*tp_getset*/ nullptr,
|
|
/*tp_base*/ nullptr,
|
|
/*tp_dict*/ nullptr,
|
|
/*tp_descr_get*/ nullptr,
|
|
/*tp_descr_set*/ nullptr,
|
|
/*tp_dictoffset*/ 0,
|
|
/*tp_init*/ nullptr,
|
|
/*tp_alloc*/ nullptr,
|
|
/*tp_new*/ nullptr,
|
|
/*tp_free*/ nullptr,
|
|
/*tp_is_gc*/ nullptr,
|
|
/*tp_bases*/ nullptr,
|
|
/*tp_mro*/ nullptr,
|
|
/*tp_cache*/ nullptr,
|
|
/*tp_subclasses*/ nullptr,
|
|
/*tp_weaklist*/ nullptr,
|
|
/*tp_del*/ nullptr,
|
|
/*tp_version_tag*/ 0,
|
|
/*tp_finalize*/ nullptr,
|
|
/*tp_vectorcall*/ nullptr,
|
|
};
|
|
|
|
static PyObject *pygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
/* sanity - should never happen */
|
|
if (self->level != -1) {
|
|
PyErr_SetString(PyExc_RuntimeError, "Already in use");
|
|
return nullptr;
|
|
}
|
|
|
|
if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
|
|
if (!pygpu_stack_is_push_model_view_ok_or_error()) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_push();
|
|
self->level = GPU_matrix_stack_level_get_model_view();
|
|
}
|
|
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
|
|
if (!pygpu_stack_is_push_projection_ok_or_error()) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_push_projection();
|
|
self->level = GPU_matrix_stack_level_get_projection();
|
|
}
|
|
else {
|
|
BLI_assert_unreachable();
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyObject *pygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self,
|
|
PyObject * /*args*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
/* sanity - should never happen */
|
|
if (self->level == -1) {
|
|
fprintf(stderr, "Not yet in use\n");
|
|
goto finally;
|
|
}
|
|
|
|
if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
|
|
const int level = GPU_matrix_stack_level_get_model_view();
|
|
if (level != self->level) {
|
|
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d\n", self->level, level);
|
|
}
|
|
if (level != 0) {
|
|
GPU_matrix_pop();
|
|
}
|
|
}
|
|
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
|
|
const int level = GPU_matrix_stack_level_get_projection();
|
|
if (level != self->level) {
|
|
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d", self->level, level);
|
|
}
|
|
if (level != 0) {
|
|
GPU_matrix_pop_projection();
|
|
}
|
|
}
|
|
else {
|
|
BLI_assert_unreachable();
|
|
}
|
|
finally:
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyObject *pygpu_matrix_push_pop_impl(int type)
|
|
{
|
|
BPyGPU_MatrixStackContext *ret = PyObject_New(BPyGPU_MatrixStackContext,
|
|
&PyGPUMatrixStackContext_Type);
|
|
ret->type = type;
|
|
ret->level = -1;
|
|
return (PyObject *)ret;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_push_pop_doc,
|
|
".. function:: push_pop()\n"
|
|
"\n"
|
|
" Context manager to ensure balanced push/pop calls, even in the case of an error.\n");
|
|
static PyObject *pygpu_matrix_push_pop(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
return pygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_MODEL_VIEW);
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_push_pop_projection_doc,
|
|
".. function:: push_pop_projection()\n"
|
|
"\n"
|
|
" Context manager to ensure balanced push/pop calls, even in the case of an error.\n");
|
|
static PyObject *pygpu_matrix_push_pop_projection(PyObject * /*self*/)
|
|
{
|
|
return pygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_PROJECTION);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Manipulate State
|
|
* \{ */
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_multiply_matrix_doc,
|
|
".. function:: multiply_matrix(matrix)\n"
|
|
"\n"
|
|
" Multiply the current stack matrix.\n"
|
|
"\n"
|
|
" :arg matrix: A 4x4 matrix.\n"
|
|
" :type matrix: :class:`mathutils.Matrix`\n");
|
|
static PyObject *pygpu_matrix_multiply_matrix(PyObject * /*self*/, PyObject *value)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
MatrixObject *pymat;
|
|
if (!Matrix_Parse4x4(value, &pymat)) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_mul(pymat->matrix);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_scale_doc,
|
|
".. function:: scale(scale)\n"
|
|
"\n"
|
|
" Scale the current stack matrix.\n"
|
|
"\n"
|
|
" :arg scale: Scale the current stack matrix.\n"
|
|
" :type scale: sequence of 2 or 3 floats\n");
|
|
static PyObject *pygpu_matrix_scale(PyObject * /*self*/, PyObject *value)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
float scale[3];
|
|
int len;
|
|
if ((len = mathutils_array_parse(
|
|
scale, 2, 3, value, "gpu.matrix.scale(): invalid vector arg")) == -1)
|
|
{
|
|
return nullptr;
|
|
}
|
|
if (len == 2) {
|
|
GPU_matrix_scale_2fv(scale);
|
|
}
|
|
else {
|
|
GPU_matrix_scale_3fv(scale);
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_scale_uniform_doc,
|
|
".. function:: scale_uniform(scale)\n"
|
|
"\n"
|
|
" :arg scale: Scale the current stack matrix.\n"
|
|
" :type scale: float\n");
|
|
static PyObject *pygpu_matrix_scale_uniform(PyObject * /*self*/, PyObject *value)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
float scalar;
|
|
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
|
|
PyErr_Format(PyExc_TypeError, "expected a number, not %.200s", Py_TYPE(value)->tp_name);
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_scale_1f(scalar);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_translate_doc,
|
|
".. function:: translate(offset)\n"
|
|
"\n"
|
|
" Scale the current stack matrix.\n"
|
|
"\n"
|
|
" :arg offset: Translate the current stack matrix.\n"
|
|
" :type offset: sequence of 2 or 3 floats\n");
|
|
static PyObject *pygpu_matrix_translate(PyObject * /*self*/, PyObject *value)
|
|
{
|
|
float offset[3];
|
|
int len;
|
|
if ((len = mathutils_array_parse(
|
|
offset, 2, 3, value, "gpu.matrix.translate(): invalid vector arg")) == -1)
|
|
{
|
|
return nullptr;
|
|
}
|
|
if (len == 2) {
|
|
GPU_matrix_translate_2fv(offset);
|
|
}
|
|
else {
|
|
GPU_matrix_translate_3fv(offset);
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Write State
|
|
* \{ */
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_reset_doc,
|
|
".. function:: reset()\n"
|
|
"\n"
|
|
" Empty stack and set to identity.\n");
|
|
static PyObject *pygpu_matrix_reset(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
GPU_matrix_reset();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_load_identity_doc,
|
|
".. function:: load_identity()\n"
|
|
"\n"
|
|
" Load an identity matrix into the stack.\n");
|
|
static PyObject *pygpu_matrix_load_identity(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
GPU_matrix_identity_set();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_load_matrix_doc,
|
|
".. function:: load_matrix(matrix)\n"
|
|
"\n"
|
|
" Load a matrix into the stack.\n"
|
|
"\n"
|
|
" :arg matrix: A 4x4 matrix.\n"
|
|
" :type matrix: :class:`mathutils.Matrix`\n");
|
|
static PyObject *pygpu_matrix_load_matrix(PyObject * /*self*/, PyObject *value)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
MatrixObject *pymat;
|
|
if (!Matrix_Parse4x4(value, &pymat)) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_set(pymat->matrix);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_load_projection_matrix_doc,
|
|
".. function:: load_projection_matrix(matrix)\n"
|
|
"\n"
|
|
" Load a projection matrix into the stack.\n"
|
|
"\n"
|
|
" :arg matrix: A 4x4 matrix.\n"
|
|
" :type matrix: :class:`mathutils.Matrix`\n");
|
|
static PyObject *pygpu_matrix_load_projection_matrix(PyObject * /*self*/, PyObject *value)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
MatrixObject *pymat;
|
|
if (!Matrix_Parse4x4(value, &pymat)) {
|
|
return nullptr;
|
|
}
|
|
GPU_matrix_projection_set(pymat->matrix);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Read State
|
|
* \{ */
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_get_projection_matrix_doc,
|
|
".. function:: get_projection_matrix()\n"
|
|
"\n"
|
|
" Return a copy of the projection matrix.\n"
|
|
"\n"
|
|
" :return: A 4x4 projection matrix.\n"
|
|
" :rtype: :class:`mathutils.Matrix`\n");
|
|
static PyObject *pygpu_matrix_get_projection_matrix(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
float matrix[4][4];
|
|
GPU_matrix_projection_get(matrix);
|
|
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, nullptr);
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_get_model_view_matrix_doc,
|
|
".. function:: get_model_view_matrix()\n"
|
|
"\n"
|
|
" Return a copy of the model-view matrix.\n"
|
|
"\n"
|
|
" :return: A 4x4 view matrix.\n"
|
|
" :rtype: :class:`mathutils.Matrix`\n");
|
|
static PyObject *pygpu_matrix_get_model_view_matrix(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
float matrix[4][4];
|
|
GPU_matrix_model_view_get(matrix);
|
|
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, nullptr);
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix_get_normal_matrix_doc,
|
|
".. function:: get_normal_matrix()\n"
|
|
"\n"
|
|
" Return a copy of the normal matrix.\n"
|
|
"\n"
|
|
" :return: A 3x3 normal matrix.\n"
|
|
" :rtype: :class:`mathutils.Matrix`\n");
|
|
static PyObject *pygpu_matrix_get_normal_matrix(PyObject * /*self*/)
|
|
{
|
|
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
|
|
|
float matrix[3][3];
|
|
GPU_matrix_normal_get(matrix);
|
|
return Matrix_CreatePyObject(&matrix[0][0], 3, 3, nullptr);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Module
|
|
* \{ */
|
|
|
|
#if (defined(__GNUC__) && !defined(__clang__))
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wcast-function-type"
|
|
#endif
|
|
|
|
static PyMethodDef pygpu_matrix__tp_methods[] = {
|
|
/* Manage Stack */
|
|
{"push", (PyCFunction)pygpu_matrix_push, METH_NOARGS, pygpu_matrix_push_doc},
|
|
{"pop", (PyCFunction)pygpu_matrix_pop, METH_NOARGS, pygpu_matrix_pop_doc},
|
|
|
|
{"push_projection",
|
|
(PyCFunction)pygpu_matrix_push_projection,
|
|
METH_NOARGS,
|
|
pygpu_matrix_push_projection_doc},
|
|
{"pop_projection",
|
|
(PyCFunction)pygpu_matrix_pop_projection,
|
|
METH_NOARGS,
|
|
pygpu_matrix_pop_projection_doc},
|
|
|
|
/* Stack (Context Manager) */
|
|
{"push_pop", (PyCFunction)pygpu_matrix_push_pop, METH_NOARGS, pygpu_matrix_push_pop_doc},
|
|
{"push_pop_projection",
|
|
(PyCFunction)pygpu_matrix_push_pop_projection,
|
|
METH_NOARGS,
|
|
pygpu_matrix_push_pop_projection_doc},
|
|
|
|
/* Manipulate State */
|
|
{"multiply_matrix",
|
|
(PyCFunction)pygpu_matrix_multiply_matrix,
|
|
METH_O,
|
|
pygpu_matrix_multiply_matrix_doc},
|
|
{"scale", (PyCFunction)pygpu_matrix_scale, METH_O, pygpu_matrix_scale_doc},
|
|
{"scale_uniform",
|
|
(PyCFunction)pygpu_matrix_scale_uniform,
|
|
METH_O,
|
|
pygpu_matrix_scale_uniform_doc},
|
|
{"translate", (PyCFunction)pygpu_matrix_translate, METH_O, pygpu_matrix_translate_doc},
|
|
|
|
/* TODO */
|
|
#if 0
|
|
{"rotate", (PyCFunction)pygpu_matrix_rotate, METH_O, pygpu_matrix_rotate_doc},
|
|
{"rotate_axis", (PyCFunction)pygpu_matrix_rotate_axis, METH_O, pygpu_matrix_rotate_axis_doc},
|
|
{"look_at", (PyCFunction)pygpu_matrix_look_at, METH_O, pygpu_matrix_look_at_doc},
|
|
#endif
|
|
|
|
/* Write State */
|
|
{"reset", (PyCFunction)pygpu_matrix_reset, METH_NOARGS, pygpu_matrix_reset_doc},
|
|
{"load_identity",
|
|
(PyCFunction)pygpu_matrix_load_identity,
|
|
METH_NOARGS,
|
|
pygpu_matrix_load_identity_doc},
|
|
{"load_matrix", (PyCFunction)pygpu_matrix_load_matrix, METH_O, pygpu_matrix_load_matrix_doc},
|
|
{"load_projection_matrix",
|
|
(PyCFunction)pygpu_matrix_load_projection_matrix,
|
|
METH_O,
|
|
pygpu_matrix_load_projection_matrix_doc},
|
|
|
|
/* Read State */
|
|
{"get_projection_matrix",
|
|
(PyCFunction)pygpu_matrix_get_projection_matrix,
|
|
METH_NOARGS,
|
|
pygpu_matrix_get_projection_matrix_doc},
|
|
{"get_model_view_matrix",
|
|
(PyCFunction)pygpu_matrix_get_model_view_matrix,
|
|
METH_NOARGS,
|
|
pygpu_matrix_get_model_view_matrix_doc},
|
|
{"get_normal_matrix",
|
|
(PyCFunction)pygpu_matrix_get_normal_matrix,
|
|
METH_NOARGS,
|
|
pygpu_matrix_get_normal_matrix_doc},
|
|
|
|
{nullptr, nullptr, 0, nullptr},
|
|
};
|
|
|
|
#if (defined(__GNUC__) && !defined(__clang__))
|
|
# pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
pygpu_matrix__tp_doc,
|
|
"This module provides access to the matrix stack.");
|
|
static PyModuleDef pygpu_matrix_module_def = {
|
|
/*m_base*/ PyModuleDef_HEAD_INIT,
|
|
/*m_name*/ "gpu.matrix",
|
|
/*m_doc*/ pygpu_matrix__tp_doc,
|
|
/*m_size*/ 0,
|
|
/*m_methods*/ pygpu_matrix__tp_methods,
|
|
/*m_slots*/ nullptr,
|
|
/*m_traverse*/ nullptr,
|
|
/*m_clear*/ nullptr,
|
|
/*m_free*/ nullptr,
|
|
};
|
|
|
|
PyObject *bpygpu_matrix_init()
|
|
{
|
|
PyObject *submodule;
|
|
|
|
submodule = PyModule_Create(&pygpu_matrix_module_def);
|
|
|
|
if (PyType_Ready(&PyGPUMatrixStackContext_Type) < 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
return submodule;
|
|
}
|
|
|
|
/** \} */
|