Skip to content

Commit

Permalink
--Separate Render-related binds for creation and def for circular refs
Browse files Browse the repository at this point in the history
  • Loading branch information
jturner65 committed Jul 19, 2024
1 parent fd5b3c7 commit a86c933
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 18 deletions.
19 changes: 15 additions & 4 deletions src/esp/bindings/Bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "esp/core/Configuration.h"
#include "esp/core/Esp.h"
#include "esp/core/RigidState.h"
#include "esp/gfx/Renderer.h"

namespace py = pybind11;
using py::literals::operator""_a;
Expand Down Expand Up @@ -58,17 +59,25 @@ PYBIND11_MODULE(habitat_sim_bindings, m) {

py::bind_map<std::map<std::string, std::string>>(m, "MapStringString");

// NOTE(msb) These need to be run in dependency order.
// TODO(msb) gfx, scene, and sensor should not cross-depend
// TODO(msb) sim and sensor should not cross-depend
esp::initEspBindings(m);
esp::core::config::initConfigBindings(m);
esp::core::initCoreBindings(m);
esp::geo::initGeoBindings(m);

// To address circular references, we build certain class binding before
// other bindings that reference it, and then complete its definition that
// includes references to those classes.
auto pySceneNode = esp::scene::createSceneNodeBind(m);
auto pyRenderCamera = esp::gfx::createRenderCameraBind(m);
auto pyRenderer = esp::gfx::createRendererBind(m);
esp::gfx::initRenderTargetBind(m);
// Sensor depends on SceneNode, RenderCamera and RenderTarget bindings
esp::sensor::initSensorBindings(m);
esp::gfx::initGfxBindings(m);
esp::gfx::initGfxBindings(m, pyRenderCamera);

esp::gfx::replay::initGfxReplayBindings(m);
// We pass the created scene node class binding to the initialization function
// to complete its definition
esp::scene::initSceneBindings(m, pySceneNode);
esp::nav::initShortestPathBindings(m);
esp::sim::initSimConfigBindings(m);
Expand All @@ -80,4 +89,6 @@ PYBIND11_MODULE(habitat_sim_bindings, m) {
esp::physics::initPhysicsObjectBindings(m);
esp::physics::initPhysicsWrapperManagerBindings(m);
esp::sim::initSimBindings(m);
// Renderer relies on simulator class bindings
esp::gfx::finalInitRenderer(m, pyRenderer);
}
44 changes: 43 additions & 1 deletion src/esp/bindings/Bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,52 @@ void initGeoBindings(pybind11::module& m);

namespace gfx {

/**
* @brief Create pybind class for RenderCamera, and partially define bindings.
* Bindings should be completed in @ref initGfxBindings, once dependent
* bindings have been created (i.e. SceneNode)
*/
pybind11::class_<RenderCamera,
Magnum::SceneGraph::PyFeature<RenderCamera>,
Magnum::SceneGraph::Camera3D,
Magnum::SceneGraph::PyFeatureHolder<RenderCamera>>
createRenderCameraBind(pybind11::module& m);

class Renderer;

/**
* @brief Create pybind class for Renderer, and partially define bindings.
* Bindings should be completed in @ref initGfxBindings, once dependent
* bindings have been created (i.e. SceneNode)
*/
pybind11::class_<esp::gfx::Renderer, std::shared_ptr<Renderer>>
createRendererBind(pybind11::module& m);

/**
* @brief Finalize Renderer bindings definitions after sim bindings class
* defined.
*/
void finalInitRenderer(
pybind11::module& m,
pybind11::class_<Renderer, std::shared_ptr<Renderer>>& renderer);

/**
* @brief Specify bindings for RenderTarget. Done separately so that it can be
* performed before Sensor bindings are defined, which depend on it.
*/
void initRenderTargetBind(pybind11::module& m);

/**
* @brief Specify bindings for constructs in esp::gfx namespace
*/
void initGfxBindings(pybind11::module& m);
void initGfxBindings(
pybind11::module& m,
pybind11::class_<RenderCamera,
Magnum::SceneGraph::PyFeature<RenderCamera>,
Magnum::SceneGraph::Camera3D,
Magnum::SceneGraph::PyFeatureHolder<RenderCamera>>&
renderCamera);

namespace replay {
/**
* @brief Specify bindings for constructs in esp::gfx::replay namespace
Expand Down
58 changes: 45 additions & 13 deletions src/esp/bindings/GfxBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,27 @@ esp::scene::SceneNode* nodeGetter(T& self) {

namespace esp {
namespace gfx {

void initGfxBindings(py::module& m) {
// ==== RenderCamera ====
py::class_<RenderCamera,
Magnum::SceneGraph::PyFeature<RenderCamera>,
Magnum::SceneGraph::Camera3D,
Magnum::SceneGraph::PyFeatureHolder<RenderCamera>>
createRenderCameraBind(py::module& m) {
py::class_<RenderCamera, Magnum::SceneGraph::PyFeature<RenderCamera>,
Magnum::SceneGraph::Camera3D,
Magnum::SceneGraph::PyFeatureHolder<RenderCamera>>
render_camera(
renderCamera(
m, "Camera",
R"(RenderCamera: The object of this class is a camera attached
to the scene node for rendering.)");

py::enum_<RenderCamera::Flag> flags{render_camera, "Flags", "Flags"};
py::enum_<RenderCamera::Flag> flags{renderCamera, "Flags", "Flags"};

flags.value("FRUSTUM_CULLING", RenderCamera::Flag::FrustumCulling)
.value("OBJECTS_ONLY", RenderCamera::Flag::ObjectsOnly)
.value("NONE", RenderCamera::Flag{});
pybindEnumOperators(flags);

render_camera
renderCamera
.def(
"set_projection_matrix",
[](RenderCamera& self, int w, int h, float n, float f, Mn::Degd fov) {
Expand All @@ -71,13 +73,12 @@ void initGfxBindings(py::module& m) {
.def(
"unproject", &RenderCamera::unproject,
R"(Unproject a 2D viewport point to a 3D ray with its origin at the camera position. Ray direction is optionally normalized. Non-normalized rays originate at the camera location and terminate at a view plane one unit down the Z axis.)",
"viewport_point"_a, "normalized"_a = true)
.def_property_readonly("node", nodeGetter<RenderCamera>,
"Node this object is attached to")
.def_property_readonly("object", nodeGetter<RenderCamera>,
"Alias to node");
"viewport_point"_a, "normalized"_a = true);

// ==== Renderer ====
return renderCamera;
} // createRenderCameraBind

py::class_<Renderer, Renderer::ptr> createRendererBind(py::module& m) {
py::class_<Renderer, Renderer::ptr> renderer(m, "Renderer");

py::enum_<Renderer::Flag> rendererFlags{renderer, "Flags", "Flags"};
Expand All @@ -86,6 +87,13 @@ void initGfxBindings(py::module& m) {
.value("NONE", Renderer::Flag{});
pybindEnumOperators(rendererFlags);

return renderer;
} // createRendererBind

void finalInitRenderer(py::module& m,
py::class_<Renderer, Renderer::ptr>& renderer) {
// ==== Renderer ====
// Add additional bindings for simulator and sensor bindings access
renderer.def(py::init(&Renderer::create<>))
.def(
"draw",
Expand Down Expand Up @@ -130,7 +138,11 @@ void initGfxBindings(py::module& m) {
R"(Binds a RenderTarget to the sensor)", "visualSensor"_a,
"flags"_a = Renderer::Flag{});

py::class_<RenderTarget>(m, "RenderTarget")
} // finalInitRenderer

void initRenderTargetBind(py::module& m) {
auto pyRenderTarget = py::class_<RenderTarget>(m, "RenderTarget");
pyRenderTarget
.def("__enter__",
[](RenderTarget& self) {
self.renderEnter();
Expand Down Expand Up @@ -176,6 +188,24 @@ void initGfxBindings(py::module& m) {
.def("render_enter", &RenderTarget::renderEnter)
.def("render_exit", &RenderTarget::renderExit);

} // initRenderTargetBind

void initGfxBindings(
py::module& m,
py::class_<RenderCamera,
Magnum::SceneGraph::PyFeature<RenderCamera>,
Magnum::SceneGraph::Camera3D,
Magnum::SceneGraph::PyFeatureHolder<RenderCamera>>&
renderCamera) {
// ==== RenderCamera ====
// Add additional bindings for SceneNode access after SceneNode bindings are
// defined
renderCamera
.def_property_readonly("node", nodeGetter<RenderCamera>,
"Node this object is attached to")
.def_property_readonly("object", nodeGetter<RenderCamera>,
"Alias to node");

py::enum_<LightPositionModel>(
m, "LightPositionModel",
R"(Defines the coordinate frame of a light source.)")
Expand All @@ -188,6 +218,7 @@ void initGfxBindings(py::module& m) {
.value("Point", LightType::Point)
.value("Directional", LightType::Directional);

// ========== LightInfo =============
py::class_<LightInfo>(
m, "LightInfo",
R"(Defines the vector, color and LightPositionModel of a single light source.
Expand All @@ -203,6 +234,7 @@ void initGfxBindings(py::module& m) {
.def(py::self == py::self)
.def(py::self != py::self);

// ========== DebugLineRender ============
py::class_<DebugLineRender, std::shared_ptr<DebugLineRender>>(
m, "DebugLineRender")
.def(
Expand Down

0 comments on commit a86c933

Please sign in to comment.