包装矩阵乘法运算符*重载 [英] Wrap matrix multiplication with operator* overload

查看:107
本文介绍了包装矩阵乘法运算符*重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试包装要在python中调用的矩阵c ++类.我希望能够使用丰富的乘法运算符(即m1 * m2)来调用矩阵乘法,但是到目前为止,我们仅设法绑定了一个函数 m3 =乘法(m1,m2)python我能够通过派生类获得相同的功能:

I have been trying to wrap a matrix c++ class to be called in python. I would like to be able to call the matrix multiplication using the rich multiply operator (ie. m1 * m2) but so far have only managed to bind a function m3 = multiply(m1, m2) which from python i was able to get the same functionality with a derived class:

class mat4(mylib.mat4):
    def __init__(self):
        super().__init__(self)
    def __mul__(self, other):
        return multiply(self, other)

但是我更喜欢只使用C ++进行更简洁的传递,如果有人有任何建议,谢谢.

But I would prefer a cleaner pass through from C++ only, if anyone has any suggestions, thank you.

推荐答案

因此,我正尝试包装一个不存在的 glm :: mat4 :: operator *(...).这是原型:

So, I was trying to wrap a glm::mat4::operator*(...) which didn't exist. Here is the prototype:

GLM_FUNC_DECL mat< 4、4,T,Q>运算符*(mat< 4,4,T,Q> const& m,T const& s); ,它接受两个 mat4 参数并返回一个 mat4

GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T const& s); which takes two mat4 arguments and returns a mat4.

所以解决方案看起来像这样:

So the solution looked something like this:

struct custom_deleter {
    glm::mat4 operator()(glm::mat4* m) {
        return *m;
    }
};

glm::mat4* mul_mat4(glm::mat4 const &mat1, glm::mat4 const &mat2) {
    glm::mat4* tmp = new glm::mat4();
    *tmp = glm::operator*(mat1, mat2);
    // create unique_ptr to manage memory to ensure memory
    // is properly cleaned up
    std::unique_ptr<glm::mat4, custom_deleter> _m( tmp );
    return _m.get();
}

然后可以将其绑定在 BOOST_PYTHON_MODULE()中,并带有:

which could then be bound in BOOST_PYTHON_MODULE() with:

python::class_<glm::mat4, boost::shared_ptr<glm::mat4>, boost::noncopyable>("mat4", python::no_init)
.def("__init__", python::make_constructor(&make_mat4))
.def("__mul__", &mul_mat4, python::return_value_policy<python::manage_new_object>())
;

这是一个完整的示例:

#include <boost/python.hpp>
#include <boost/make_shared.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp>

struct vec3Wrap : glm::vec3, boost::python::wrapper<glm::vec3>
{
    vec3Wrap(float x, float y, float z): glm::vec3(x, y, z) {}
    vec3Wrap(float a): glm::vec3(a, a, a) {}
    vec3Wrap(): glm::vec3(){}
};

struct custom_deleter_vec {
    glm::vec3 operator()(glm::vec3* f){
        return *f;
    }
};

glm::vec3* mul_vec3(glm::vec3 const &v1, float const &f) {
    glm::vec3* tmp = new glm::vec3();
    *tmp = glm::operator*(v1, f);
    std::unique_ptr<glm::vec3, custom_deleter_vec> _v( tmp );
    return _v.get();
}

glm::vec3* add_vec3(glm::vec3 const &v1, glm::vec3 const &v2) {
    glm::vec3* tmp = new glm::vec3();
    *tmp = glm::operator+(v1, v2);
    std::unique_ptr<glm::vec3, custom_deleter_vec> _v( tmp );
    return _v.get();
}

boost::shared_ptr<glm::vec3> make_vec3(float x, float y, float z)
{
    return boost::make_shared<glm::vec3>(x, y, z);
}

struct custom_deleter {
    glm::mat4 operator()(glm::mat4* m) {
        return *m;
    }
};

glm::mat4* mul_mat4(glm::mat4 const &mat1, glm::mat4 const &mat2) {
    glm::mat4* tmp = new glm::mat4();
    *tmp = glm::operator*(mat1, mat2);
    std::unique_ptr<glm::mat4, custom_deleter> _m( tmp );
    return _m.get();
}

std::string print_mat4(glm::mat4 const &m) {
    return glm::to_string(m);
}

boost::shared_ptr<glm::mat4> make_mat4(float m)
{
    return boost::make_shared<glm::mat4>(m);
}

glm::mat4* _lookAt (glm::vec3 const &eye, glm::vec3 const &center, glm::vec3 const &up)
{
    glm::mat4 *tmp = new glm::mat4();
    *tmp = glm::lookAt(eye, center, up);
    std::unique_ptr<glm::mat4, custom_deleter> m( tmp );
    return m.get();
}

glm::mat4* _perspective(float const &fovy, float const &aspect, float const &near, float const &far)
{
    glm::mat4 *tmp = new glm::mat4();
    *tmp = glm::perspective(fovy, aspect, near, far);
    std::unique_ptr<glm::mat4, custom_deleter> m( tmp );
    return m.get();
}

int main() {

    return 0;
}

BOOST_PYTHON_MODULE(example)
{
    namespace python = boost::python;

    python::class_<glm::mat4, boost::shared_ptr<glm::mat4>, boost::noncopyable>("mat4", python::no_init)
    .def("__init__", python::make_constructor(&make_mat4))
    .def("__mul__", &mul_mat4, python::return_value_policy<python::manage_new_object>())
    .def("__str__", &print_mat4);
    python::def("perspective", _perspective, python::return_value_policy<python::manage_new_object>());
    python::def("lookAt", _lookAt, python::return_value_policy<python::manage_new_object>());

    python::class_<glm::vec3, boost::shared_ptr<glm::vec3>, boost::noncopyable>("vec3", python::no_init)
    .def("__init__", python::make_constructor(&make_vec3));
    // .def("__mul__", &mul_vec3, python::return_value_policy<python::manage_new_object>())
    // .def("__imul__", &mul_vec3, python::return_value_policy<python::manage_new_object>())
    // .def("__add__", &add_vec3, python::return_value_policy<python::manage_new_object>())
    // .def("__str__", &print_vec3)
    // .def_readwrite("x", &vec3::x)
    // .def_readwrite("y", &vec3::y)
    // .def_readwrite("z", &vec3::z);
}

在Python方面可以允许一些漂亮的东西:

Which can allow for some pretty neat stuff on the Python side:

from example import mat4, perspective, lookAt, vec3
model = mat4(1.0)
view = lookAt(vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, -5.0), vec3(0.0, 1.0, 0.0))
projection = perspective(view, 800, 600, 0.1, 1000.0)
MVP = projection * view * model

这篇关于包装矩阵乘法运算符*重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆