Skip to content

Commit

Permalink
Frustum bindings
Browse files Browse the repository at this point in the history
Signed-off-by: Piotr Barejko <[email protected]>
  • Loading branch information
bareya committed Jan 20, 2025
1 parent b6b7e3c commit 251e46a
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 107 deletions.
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;

/// @{
/// @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
55 changes: 0 additions & 55 deletions src/pybind11/PyBindImath/PyBindImathFrustum

This file was deleted.

252 changes: 206 additions & 46 deletions src/pybind11/PyBindImath/PyBindImathFrustum.cpp
Original file line number Diff line number Diff line change
@@ -1,59 +1,219 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

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

namespace PyBindImath {
namespace py = pybind11;
namespace {

template<typename T>
struct GetClassName {};

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

template <>
struct GetClassName<Imath::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::Plane3<T>* planes) -> void
{
self.planes(planes);
})
.def("planes", [](F const& self, Imath::Plane3<T> *p, Imath::Matrix44<T> const& m) -> void
{
self.planes(p, m);
})
.def("planes", [](F const& self, Imath::Matrix44<T> const& m)
{
Imath::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::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::Line3<T> {
if(seq.size() != 2) {
throw std::invalid_argument ( "projectScreenToRay expects a sequence of length 2");
}

Imath::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::Vec2<T> {
if(seq.size() != 3) {
throw std::invalid_argument ( "projectPointToScreen expects a sequence of length 3");
}

Imath::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::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::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::Frustumf>(m, "Frustumf");
register_Frustum<Imath::Frustumd>(m, "Frustumd");
}

}
} // PyBindImath
Loading

0 comments on commit 251e46a

Please sign in to comment.