// Copyright 2022 DeepMind Technologies Limited // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include "errors.h" #include "function_traits.h" #include "functions.h" #include "raw.h" #include "structs.h" #include #include #include namespace mujoco::python { namespace _impl { template <> class MjWrapper : public WrapperBase { public: MjWrapper(); MjWrapper(const MjModelWrapper& model, int fontscale); MjWrapper(const MjWrapper&) = delete; MjWrapper(MjWrapper&&) = default; ~MjWrapper() = default; void Free(); #define X(var) \ py_array_or_tuple_t< \ std::remove_all_extents_t> \ var X(fogRGBA); X(auxWidth); X(auxHeight); X(auxSamples); X(auxFBO); X(auxFBO_r); X(auxColor); X(auxColor_r); X(mat_texid); X(mat_texuniform); X(mat_texrepeat); X(textureType); X(texture); X(skinvertVBO); X(skinnormalVBO); X(skintexcoordVBO); X(skinfaceVBO); X(charWidth); X(charWidthBig); #undef X }; using MjrContextWrapper = MjWrapper; template <> struct enable_if_mj_struct { using type = void; }; static void MjrContextCapsuleDestructor(PyObject* pyobj) { auto* ptr = static_cast(PyCapsule_GetPointer(pyobj, nullptr)); mjr_freeContext(ptr); delete ptr; } #define X(var) var(InitPyArray(ptr_->var, owner_)) #define X_SKIN(var) var(InitPyArray(std::array{ptr_->nskin}, ptr_->var, owner_)) MjrContextWrapper::MjWrapper() : WrapperBase([]() { raw::MjrContext *const ctx = new raw::MjrContext; mjr_defaultContext(ctx); return ctx; }()), X(fogRGBA), X(auxWidth), X(auxHeight), X(auxSamples), X(auxFBO), X(auxFBO_r), X(auxColor), X(auxColor_r), X(mat_texid), X(mat_texuniform), X(mat_texrepeat), X(textureType), X(texture), X_SKIN(skinvertVBO), X_SKIN(skinnormalVBO), X_SKIN(skintexcoordVBO), X_SKIN(skinfaceVBO), X(charWidth), X(charWidthBig) {} MjrContextWrapper::MjWrapper(const MjModelWrapper& model, int fontscale) : WrapperBase([fontscale](const raw::MjModel* m) { raw::MjrContext *const ctx = new raw::MjrContext; mjr_defaultContext(ctx); InterceptMjErrors(mjr_makeContext)(m, ctx, fontscale); return ctx; }(model.get()), &MjrContextCapsuleDestructor), X(fogRGBA), X(auxWidth), X(auxHeight), X(auxSamples), X(auxFBO), X(auxFBO_r), X(auxColor), X(auxColor_r), X(mat_texid), X(mat_texuniform), X(mat_texrepeat), X(textureType), X(texture), X_SKIN(skinvertVBO), X_SKIN(skinnormalVBO), X_SKIN(skintexcoordVBO), X_SKIN(skinfaceVBO), X(charWidth), X(charWidthBig) {} #undef X_SKIN #undef X void MjrContextWrapper::Free() { // mjr_freeContext is safe to call multiple times. InterceptMjErrors(mjr_freeContext)(ptr_); } } // namespace _impl namespace { PYBIND11_MODULE(_render, pymodule) { namespace py = ::pybind11; namespace traits = python_traits; using _impl::MjModelWrapper; using _impl::MjrContextWrapper; // Import the _structs module so that pybind11 knows about Python bindings // for MjWrapper types and therefore generates prettier docstrings. py::module::import("mujoco._structs"); py::class_ mjrContext(pymodule, "MjrContext"); mjrContext.def(py::init<>()); mjrContext.def(py::init()); mjrContext.def( "free", [](MjrContextWrapper& self) { self.Free(); }, py::doc("Frees resources in current active OpenGL context, sets struct " "to default.")); #define X(var) \ mjrContext.def_property( \ #var, [](const MjrContextWrapper& c) { return c.get()->var; }, \ [](MjrContextWrapper& c, mjtNum rhs) { c.get()->var = rhs; }) X(lineWidth); X(shadowClip); X(shadowScale); X(fogStart); X(fogEnd); X(shadowSize); X(offWidth); X(offHeight); X(offSamples); X(fontScale); X(offFBO); X(offFBO_r); X(offColor); X(offColor_r); X(offDepthStencil); X(offDepthStencil_r); X(shadowFBO); X(shadowTex); X(ntexture); X(basePlane); X(baseMesh); X(baseHField); X(baseBuiltin); X(baseFontNormal); X(baseFontShadow); X(baseFontBig); X(rangePlane); X(rangeMesh); X(rangeHField); X(rangeBuiltin); X(rangeFont); X(nskin); X(charHeight); X(charHeightBig); X(glInitialized); X(windowAvailable); X(windowSamples); X(windowStereo); X(windowDoublebuffer); X(currentBuffer); X(readPixelFormat); X(readDepthMap); #undef X #define X(var) \ mjrContext.def_property_readonly( \ #var, [](const MjrContextWrapper& c) { return c.get()->var; }) X(nskin); #undef X #define X(var) DefinePyArray(mjrContext, #var, &MjrContextWrapper::var) X(fogRGBA); X(auxWidth); X(auxHeight); X(auxSamples); X(auxFBO); X(auxFBO_r); X(auxColor); X(auxColor_r); X(mat_texid); X(mat_texuniform); X(mat_texrepeat); X(textureType); X(texture); X(skinvertVBO); X(skinnormalVBO); X(skintexcoordVBO); X(skinfaceVBO); X(charWidth); X(charWidthBig); #undef X using EigenUnsignedCharVectorX = Eigen::Vector; using EigenFloatVectorX = Eigen::Vector; // Skipped: mjr_defaultContext (have MjrContext.__init__) // Skipped: mjr_makeContext (have MjrContext.__init__) Def(pymodule); Def(pymodule); // Skipped: mjr_freeContext (have MjrContext.__del__) Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); DefWithGil( pymodule, [](std::optional> rgb, std::optional> depth, const raw::MjrRect* viewport, const raw::MjrContext* con) { std::uint8_t* const rgb_data = rgb.has_value() ? rgb->mutable_data() : nullptr; float* const depth_data = depth.has_value() ? depth->mutable_data() : nullptr; { py::gil_scoped_release no_gil; return InterceptMjErrors(::mjr_readPixels)(rgb_data, depth_data, *viewport, con); } }); Def( pymodule, [](std::optional> rgb, std::optional> depth, const raw::MjrRect* viewport, const raw::MjrContext* con) { return InterceptMjErrors(::mjr_drawPixels)( rgb.has_value() ? rgb->data() : nullptr, depth.has_value() ? depth->data() : nullptr, *viewport, con); }); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); Def(pymodule); } // PYBIND11_MODULE } // namespace } // namespace mujoco::python