Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quat, Frustum Python bindings #464

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Imath/ImathFrustum.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Frustum
{
public:
using value_type = T;

/// @{
/// @name Constructors and Assignment
///
Expand Down
2 changes: 2 additions & 0 deletions src/Imath/ImathMatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,8 @@ template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Matrix33
template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Matrix44
{
public:
using value_type = T;
bareya marked this conversation as resolved.
Show resolved Hide resolved

/// @{
/// @name Direct access to elements

Expand Down
9 changes: 5 additions & 4 deletions src/pybind11/PyBindImath/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ set(PYBINDIMATH_SOURCES
PyBindImathVec.cpp
PyBindImathPlane.cpp
PyBindImathLine.cpp

PyBindImathMatrix44.cpp

# PyBindImathEuler build Error pybind test
# PyBindImathFrustum build failing
PyBindImathFrustum.cpp
)

set(PYBINDIMATH_HEADERS
Expand Down Expand Up @@ -69,12 +70,12 @@ endif()
if (IMATH_INSTALL)

# module

install(TARGETS ${PYBINDIMATH_MODULE} DESTINATION ${PYTHON_INSTALL_DIR} COMPONENT python)

# shared library

install(TARGETS ${PYBINDIMATH_LIBRARY}
install(TARGETS ${PYBINDIMATH_LIBRARY}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand Down
4 changes: 3 additions & 1 deletion src/pybind11/PyBindImath/PyBindImath.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ PYBINDIMATH_EXPORT void register_imath_vec(pybind11::module& m);
PYBINDIMATH_EXPORT void register_imath_box(pybind11::module& m);
PYBINDIMATH_EXPORT void register_imath_plane(pybind11::module& m);
PYBINDIMATH_EXPORT void register_imath_line(pybind11::module& m);
PYBINDIMATH_EXPORT void register_imath_matrix(pybind11::module& m);

// PYBINDIMATH_EXPORT void register_imath_euler(pybind11::module& m)
// PYBINDIMATH_EXPORT void register_imath_frustum(pybind11::module& m)
PYBINDIMATH_EXPORT void register_imath_frustum(pybind11::module& m);
}

#endif
247 changes: 206 additions & 41 deletions src/pybind11/PyBindImath/PyBindImathFrustum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,220 @@

#include "PyBindImath.h"
#include <ImathFrustum.h>
#include <ImathVec.h>
#include <ImathMatrix.h>

namespace PyBindImath {
namespace py = pybind11;
namespace {

template<typename T>
struct GetClassName {};

template <>
struct GetClassName<IMATH_NAMESPACE::Frustumf> {
static constexpr const char* value = "Frustumf";
};

template <class T, class V, class S>
void register_frustum(pybind11::module& m, const char *name)
template <>
struct GetClassName<IMATH_NAMESPACE::Frustumd> {
static constexpr const char* value = "Frustumd";
};

template <typename F, typename T = typename F::value_type>
void register_Frustum(py::module& m, const char *name)
{
pybind11::class_<T> c(m, name);
c.def(pybind11::init<>(), "Uninitialized by default")
.def(pybind11::init<T>(), pybind11::arg("frustum"), "Copy constructor")
.def(pybind11::init<S, S, S, S>(), pybind11::arg("nearPlane"), pybind11::arg("farPlane"), pybind11::arg("fovx"), pybind11::arg("aspect"), "Initialize with basic frustum properties")

.def_readwrite("nearPlane", &T::nearPlane, "The near clipping plane")
.def_readwrite("farPlane", &T::farPlane, "The far clipping plane")
.def_readwrite("fovx", &T::fovx, "The field of view in x direction")
.def_readwrite("aspect", &T::aspect, "The aspect ratio")

.def("set", pybind11::overload_cast<S, S, S, S>(&T::set), pybind11::arg("nearPlane"), pybind11::arg("farPlane"), pybind11::arg("fovx"), pybind11::arg("aspect"), "Set frustum properties")
.def("projectionMatrix", &T::projectionMatrix, "Returns the projection matrix of the frustum")
.def("transform", &T::transform, pybind11::arg("matrix"), "Applies a transformation matrix to the frustum")
.def("intersects", [](T& self, const V& point) {
bool result = self.intersects(point);
return result;
}, pybind11::arg("point"), "Determines if the point is inside the frustum")
py::class_<F>(m, name)
.def(py::init<>(), "Frustum() default construction")
.def(py::init<F>(), py::arg("frustum"), "Copy constructor")
.def(py::init<T, T, T, T, T, T, bool>(), "Frustum(nearPlane,farPlane,left,right,top,bottom,ortho) construction")
.def(py::init<T, T, T, T, T>(), "Frustum(nearPlane,farPlane,fovx,fovy,aspect) construction")

.def("set", py::overload_cast<T, T, T, T, T, T, bool>(&F::set),
"F.set(nearPlane, farPlane, left, right, top, bottom, "
"[ortho])\n"
"F.set(nearPlane, farPlane, fovx, fovy, aspect) "
" -- sets the entire state of "
"frustum F as specified. Only one of "
"fovx or fovy may be non-zero.")
.def("set", py::overload_cast<T, T, T, T, T>(&F::set))

.def("modifyNearAndFar", &F::modifyNearAndFar,
"F.modifyNearAndFar(nearPlane, farPlane) -- modifies "
"the already-valid frustum F as specified")

.def("setOrthographic", &F::setOrthographic,
"F.setOrthographic(b) -- modifies the "
"already-valid frustum F to be orthographic "
"or not")

.def("nearPlane", &F::nearPlane,
"F.nearPlane() -- returns the coordinate of the "
"near clipping plane of frustum F")

.def("farPlane", &F::farPlane,
"F.farPlane() -- returns the coordinate of the "
"far clipping plane of frustum F")

// The following two functions provide backwards compatibility
// with the previous API for this class.

.def("near", &F::nearPlane,
"F.near() -- returns the coordinate of the "
"near clipping plane of frustum F")

.def("screenToWorld", [](T& self, const V& screenPoint) {
V worldPoint;
self.screenToWorld(screenPoint, worldPoint);
return worldPoint;
}, pybind11::arg("screenPoint"), "Convert a screen space point to world space")
.def("far", &F::farPlane,
"F.far() -- returns the coordinate of the "
"far clipping plane of frustum F")

.def("left", &F::left,
"F.left() -- returns the left coordinate of "
"the near clipping window of frustum F")

.def("right", &F::right,
"F.right() -- returns the right coordinate of "
"the near clipping window of frustum F")

.def("top", &F::top,
"F.top() -- returns the top coordinate of "
"the near clipping window of frustum F")

.def("bottom", &F::bottom,
"F.bottom() -- returns the bottom coordinate "
"of the near clipping window of frustum F")

.def("orthographic", &F::orthographic,
"F.orthographic() -- returns whether frustum "
"F is orthographic or not")

.def("planes", [](F const& self, IMATH_NAMESPACE::Plane3<T>* planes) -> void
{
self.planes(planes);
})
.def("planes", [](F const& self, IMATH_NAMESPACE::Plane3<T> *p, IMATH_NAMESPACE::Matrix44<T> const& m) -> void
{
self.planes(p, m);
})
.def("planes", [](F const& self, IMATH_NAMESPACE::Matrix44<T> const& m)
{
IMATH_NAMESPACE::Plane3<T> p[6];
self.planes(p, m);
return py::make_tuple(p[0], p[1], p[2], p[3], p[4], p[5]);
})
.def("planes", [](F const& self)
{
IMATH_NAMESPACE::Plane3<T> p[6];
self.planes(p);

.def("worldToScreen", [](T& self, const V& worldPoint) {
V screenPoint;
self.worldToScreen(worldPoint, screenPoint);
return screenPoint;
}, pybind11::arg("worldPoint"), "Convert a world space point to screen space")
return py::make_tuple(p[0],p[1],p[2],p[3],p[4],p[5]);
})

.def("fovx", &F::fovx,
"F.fovx() -- derives and returns the "
"x field of view (in radians) for frustum F")

.def("fovy", &F::fovy,
"F.fovy() -- derives and returns the "
"y field of view (in radians) for frustum F")

.def("aspect", &F::aspect,
"F.aspect() -- derives and returns the "
"aspect ratio for frustum F")

.def("projectionMatrix", &F::projectionMatrix,
"F.projectionMatrix() -- derives and returns "
"the projection matrix for frustum F")

.def("window", &F::window,
"F.window(l,r,b,t) -- takes a rectangle in "
"the screen space (i.e., -1 <= l <= r <= 1, "
"-1 <= b <= t <= 1) of F and returns a new "
"Frustum whose near clipping-plane window "
"is that rectangle in local space")

.def("projectScreenToRay", &F::projectScreenToRay,
"F.projectScreenToRay(V) -- returns a Line3 "
"through V, a V2 point in screen space")

.def("projectScreenToRay", [](F const& self, py::sequence const& seq) -> IMATH_NAMESPACE::Line3<T> {
if(seq.size() != 2) {
throw std::invalid_argument ( "projectScreenToRay expects a sequence of length 2");
}

IMATH_NAMESPACE::Vec2<T> const point{py::cast<T>(seq[0]), py::cast<T>(seq[1])};
return self.projectScreenToRay(point);
})

.def("projectPointToScreen", &F::projectPointToScreen,
"F.projectPointToScreen(V) -- returns the "
"projection of V3 V into screen space")

.def("projectPointToScreen", [](F const& self, py::sequence const& seq) -> IMATH_NAMESPACE::Vec2<T> {
if(seq.size() != 3) {
throw std::invalid_argument ( "projectPointToScreen expects a sequence of length 3");
}

IMATH_NAMESPACE::Vec3<T> const point{py::cast<T>(seq[0]), py::cast<T>(seq[1]), py::cast<T>(seq[2])};
return self.projectPointToScreen(point);
})

.def("__str__", [](const T &obj) {
std::stringstream ss;
ss << obj;
return ss.str();
});
.def("ZToDepth", &F::ZToDepth,
"F.ZToDepth(z, zMin, zMax) -- returns the "
"depth (Z in the local space of the "
"frustum F) corresponding to z (a result of "
"transformation by F's projection matrix) "
"after normalizing z to be between zMin "
"and zMax")

.def("normalizedZToDepth", &F::normalizedZToDepth,
"F.normalizedZToDepth(z) -- returns the "
"depth (Z in the local space of the "
"frustum F) corresponding to z (a result of "
"transformation by F's projection matrix), "
"which is assumed to have been normalized "
"to [-1, 1]")

.def("DepthToZ", &F::DepthToZ,
"F.DepthToZ(depth, zMin, zMax) -- converts "
"depth (Z in the local space of the frustum "
"F) to z (a result of transformation by F's "
"projection matrix) which is normalized to "
"[zMin, zMax]")

.def("worldRadius", &F::worldRadius,
"F.worldRadius(V, r) -- returns the radius "
"in F's local space corresponding to the "
"point V and radius r in screen space")

.def("worldRadius", [](F const& self, py::sequence const& seq, T radius) -> T {
if(seq.size() != 3) {
throw std::invalid_argument ( "worldRadius expects a sequence of length 3");
}

IMATH_NAMESPACE::Vec3<T> const point{py::cast<T>(seq[0]), py::cast<T>(seq[1]), py::cast<T>(seq[2])};
return self.worldRadius(point, radius);
})

.def("screenRadius", &F::screenRadius,
"F.screenRadius(V, r) -- returns the radius "
"in screen space corresponding to "
"the point V and radius r in F's local "
"space")

.def("screenRadius", [](F const& self, py::sequence const& seq, T radius) -> T{
if(seq.size() != 3) {
throw std::invalid_argument ("screenRadius expects a sequence of length 3");
}

IMATH_NAMESPACE::Vec3<T> const point{py::cast<T>(seq[0]), py::cast<T>(seq[1]), py::cast<T>(seq[2])};
return self.screenRadius(point, radius);
})
;
}

void register_imath_frustum(pybind11::module &m)
} // namespace

void register_imath_frustum(py::module &m)
{
register_frustum<IMATH_NAMESPACE::Frustumf, IMATH_NAMESPACE::V3f, IMATH_NAMESPACE::M44f, float>(m, "Frustumf");
register_frustum<IMATH_NAMESPACE::Frustumd, IMATH_NAMESPACE::V3d, IMATH_NAMESPACE::M44d, double>(m, "Frustumd");
register_Frustum<IMATH_NAMESPACE::Frustumf>(m, "Frustumf");
register_Frustum<IMATH_NAMESPACE::Frustumd>(m, "Frustumd");
}

}
} // PyBindImath
Loading
Loading