diff --git a/src/experimental/filament/filament/filament_context.cc b/src/experimental/filament/filament/filament_context.cc index e367b44f..906c32e3 100644 --- a/src/experimental/filament/filament/filament_context.cc +++ b/src/experimental/filament/filament/filament_context.cc @@ -87,7 +87,7 @@ FilamentContext::FrameHandle FilamentContext::Render( } bool render_began = false; - RenderTarget* current_target = nullptr; + mjrRenderTarget* current_target = nullptr; for (const RenderRequest& request : requests) { if (request.target != current_target && render_began) { renderer_->endFrame(); @@ -126,7 +126,8 @@ FilamentContext::FrameHandle FilamentContext::Render( scene_view_request.draw_mode = request.draw_mode; scene_view_request.viewport = {0, 0, request.width, request.height}; scene_view_request.camera = request.camera; - request.scene->Render(renderer_, scene_view_request); + SceneView* scene_view = SceneView::downcast(request.scene); + scene_view->Render(renderer_, scene_view_request); } } else { if (read_requests.empty()) { @@ -146,13 +147,16 @@ FilamentContext::FrameHandle FilamentContext::Render( break; } if (render_began) { + RenderTarget* render_target = RenderTarget::downcast(request.target); + SceneView::RenderRequest scene_view_request; scene_view_request.draw_mode = request.draw_mode; scene_view_request.viewport = {0, 0, request.width, request.height}; scene_view_request.camera = request.camera; - scene_view_request.target = request.target; - request.scene->Render(renderer_, scene_view_request); - request.target->ReadColorPixels(renderer_, read_request.output, + scene_view_request.target = render_target; + SceneView* scene_view = SceneView::downcast(request.scene); + scene_view->Render(renderer_, scene_view_request); + render_target->ReadColorPixels(renderer_, read_request.output, read_request.num_bytes); } } diff --git a/src/experimental/filament/filament/filament_context.h b/src/experimental/filament/filament/filament_context.h index 391e9818..2e98acaf 100644 --- a/src/experimental/filament/filament/filament_context.h +++ b/src/experimental/filament/filament/filament_context.h @@ -35,15 +35,18 @@ namespace mujoco { // Manages the filament renderer and provides APIs for rendering scenes. -class FilamentContext { +class FilamentContext : public mjrfContext { public: explicit FilamentContext(const mjrFilamentConfig* config); ~FilamentContext(); + FilamentContext(const FilamentContext&) = delete; + FilamentContext& operator=(const FilamentContext&) = delete; + // Information needed to render a single image of a scene. struct RenderRequest { // The scene to render. - SceneView* scene = nullptr; + mjrScene* scene = nullptr; // The method (e.g. Color, Depth, Segmentation, etc.) to use for rendering. DrawMode draw_mode = DrawMode::Color; @@ -58,12 +61,12 @@ class FilamentContext { // The render target into which to render the image. If nullptr, the image // will be rendered to the window (as previously configured in // mjrFilamentConfig::native_window). - RenderTarget* target = nullptr; + mjrRenderTarget* target = nullptr; }; // Information needed to read pixels from a render target. struct ReadPixelsRequest { - RenderTarget* target = nullptr; + mjrRenderTarget* target = nullptr; // The buffer into which the read pixels will be written. uint8_t* output = nullptr; @@ -107,8 +110,12 @@ class FilamentContext { ObjectManager* GetObjectManager() const { return object_manager_.get(); } - FilamentContext(const FilamentContext&) = delete; - FilamentContext& operator=(const FilamentContext&) = delete; + static FilamentContext* downcast(mjrfContext* context) { + return static_cast(context); + } + static const FilamentContext* downcast(const mjrfContext* context) { + return static_cast(context); + } private: mjrFilamentConfig config_; diff --git a/src/experimental/filament/filament/light.cc b/src/experimental/filament/filament/light.cc index bdc1f2cd..d79a1551 100644 --- a/src/experimental/filament/filament/light.cc +++ b/src/experimental/filament/filament/light.cc @@ -56,9 +56,10 @@ Light::Light(filament::Engine* engine, const mjrLightParams& params) filament::IndirectLight::Builder builder; if (params.texture) { // Allow null textures for fallback lights. - builder.reflections(params.texture->GetFilamentTexture()); + const Texture* texture = Texture::downcast(params.texture); + builder.reflections(texture->GetFilamentTexture()); const Texture::SphericalHarmonics* spherical_harmonics = - params.texture->GetSphericalHarmonics(); + texture->GetSphericalHarmonics(); if (spherical_harmonics != nullptr) { builder.irradiance(3, *spherical_harmonics); } diff --git a/src/experimental/filament/filament/light.h b/src/experimental/filament/filament/light.h index 93ad0bb8..d58dbdd0 100644 --- a/src/experimental/filament/filament/light.h +++ b/src/experimental/filament/filament/light.h @@ -21,6 +21,7 @@ #include #include #include "experimental/filament/filament/texture.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -31,7 +32,7 @@ struct mjrLightParams { // The type of light (e.g. spot, point, directional, etc.) mjrLightType type; // The texture to use for image lights. - const Texture* texture; + const mjrTexture* texture; // The color of the light. float color[3]; // The intensity of the light, in candela. @@ -53,7 +54,7 @@ struct mjrLightParams { void mjr_defaultLightParams(mjrLightParams* params); // Manages the filament Entities for a single mjvLight. -class Light { +class Light : public mjrLight { public: Light(filament::Engine* engine, const mjrLightParams& params); ~Light() noexcept; @@ -84,6 +85,13 @@ class Light { void Enable(); void Disable(); + static Light* downcast(mjrLight* light) { + return static_cast(light); + } + static const Light* downcast(const mjrLight* light) { + return static_cast(light); + } + private: filament::Engine* engine_ = nullptr; filament::IndirectLight* ibl_ = nullptr; diff --git a/src/experimental/filament/filament/mesh.h b/src/experimental/filament/filament/mesh.h index 3b7fc5ab..9746e4ab 100644 --- a/src/experimental/filament/filament/mesh.h +++ b/src/experimental/filament/filament/mesh.h @@ -31,6 +31,7 @@ #include #include #include +#include "experimental/filament/render_context_filament.h" // Functions for creating filament vertex and index buffers. namespace mujoco { @@ -138,13 +139,16 @@ struct mjrMeshData { void mjr_defaultMeshData(mjrMeshData* data); // Owns a Vertex and Index buffer representing a geometry mesh. -class Mesh { +class Mesh : public mjrMesh { public: // Creates a Mesh from the given MeshData. Mesh(filament::Engine* engine, const mjrMeshData& data); ~Mesh(); + Mesh(const Mesh&) = delete; + Mesh& operator=(const Mesh&) = delete; + // Returns the filament IndexBuffer for the mesh. filament::IndexBuffer* GetFilamentIndexBuffer() const; @@ -163,8 +167,12 @@ class Mesh { // Returns the bounds of the mesh. filament::Box GetBounds() const; - Mesh(const Mesh&) = delete; - Mesh& operator=(const Mesh&) = delete; + static Mesh* downcast(mjrMesh* mesh) { + return static_cast(mesh); + } + static const Mesh* downcast(const mjrMesh* mesh) { + return static_cast(mesh); + } private: void BuildVertexBuffer(const mjrMeshData& data); diff --git a/src/experimental/filament/filament/render_target.h b/src/experimental/filament/filament/render_target.h index b731a567..9e5aed68 100644 --- a/src/experimental/filament/filament/render_target.h +++ b/src/experimental/filament/filament/render_target.h @@ -22,6 +22,7 @@ #include #include #include "experimental/filament/filament/texture.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -35,7 +36,7 @@ struct mjrRenderTargetConfig { void mjr_defaultRenderTargetConfig(mjrRenderTargetConfig* config); // Manages a filament RenderTarget and the textures which are bound to it. -class RenderTarget { +class RenderTarget : public mjrRenderTarget { public: // Defines the types of textures to create for the color and depth // attachments. @@ -62,6 +63,13 @@ class RenderTarget { // Returns the underlying filament render target. filament::RenderTarget* GetFilamentRenderTarget() const; + static RenderTarget* downcast(mjrRenderTarget* render_target) { + return static_cast(render_target); + } + static const RenderTarget* downcast(const mjrRenderTarget* render_target) { + return static_cast(render_target); + } + private: void Destroy(); diff --git a/src/experimental/filament/filament/renderable.h b/src/experimental/filament/filament/renderable.h index a0da8166..35f9028a 100644 --- a/src/experimental/filament/filament/renderable.h +++ b/src/experimental/filament/filament/renderable.h @@ -29,6 +29,7 @@ #include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/mesh.h" #include "experimental/filament/filament/object_manager.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -61,7 +62,7 @@ void mjr_defaultRenderableParams(mjrRenderableParams* params); // the user specifies the MaterialParams and MaterialTextures to use with the // ShadingModel. Its these properties that ultimately define the actual material // of the Renderable. -class Renderable { +class Renderable : public mjrRenderable { public: // Default filament values for priority and layer mask. static constexpr std::uint8_t kDefaultPriority = 4; @@ -139,6 +140,13 @@ class Renderable { // Returns the filament Engine managing the renderables. filament::Engine* GetEngine(); + static Renderable* downcast(mjrRenderable* renderable) { + return static_cast(renderable); + } + static const Renderable* downcast(const mjrRenderable* renderable) { + return static_cast(renderable); + } + private: struct Part { utils::Entity entity; diff --git a/src/experimental/filament/filament/scene_view.h b/src/experimental/filament/filament/scene_view.h index 59a3e9b3..f35110f8 100644 --- a/src/experimental/filament/filament/scene_view.h +++ b/src/experimental/filament/filament/scene_view.h @@ -32,6 +32,7 @@ #include "experimental/filament/filament/renderable.h" #include "experimental/filament/filament/render_target.h" #include "experimental/filament/filament/texture.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -40,11 +41,14 @@ namespace mujoco { // The filament Scene is populated with the objects (e.g. lights, renderables, // skybox, etc.). It manages multiple views to support a variety of draw modes // (e.g. normal, depth, segmentation, etc.) as well as reflective surfaces. -class SceneView { +class SceneView : public mjrScene { public: SceneView(filament::Engine* engine); ~SceneView(); + SceneView(const SceneView&) = delete; + SceneView& operator=(const SceneView&) = delete; + // Adds/removes entities from the scene. void AddToScene(Light* light); void RemoveFromScene(Light* light); @@ -90,8 +94,12 @@ class SceneView { ColorGradingOptions GetColorGradingOptions() const; void SetColorGradingOptions(const ColorGradingOptions& opts); - SceneView(const SceneView&) = delete; - SceneView& operator=(const SceneView&) = delete; + static SceneView* downcast(mjrScene* scene) { + return static_cast(scene); + } + static const SceneView* downcast(const mjrScene* scene) { + return static_cast(scene); + } private: // Marks a renderable as reflective. Reflective renderables have to be diff --git a/src/experimental/filament/filament/texture.h b/src/experimental/filament/filament/texture.h index e51bbfff..764ae911 100644 --- a/src/experimental/filament/filament/texture.h +++ b/src/experimental/filament/filament/texture.h @@ -15,13 +15,12 @@ #ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_TEXTURE_H_ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_TEXTURE_H_ -#include - #include #include #include #include #include +#include "experimental/filament/render_context_filament.h" // Functions for creating filament textures. namespace mujoco { @@ -84,7 +83,7 @@ struct mjrTextureConfig { void mjr_defaultTextureConfig(mjrTextureConfig* config); // Wrapper around a filament::Texture. -class Texture { +class Texture : public mjrTexture { public: // Flags for internal use. struct InternalFlags { @@ -99,6 +98,9 @@ class Texture { ~Texture(); + Texture(const Texture&) = delete; + Texture& operator=(const Texture&) = delete; + // Uploads the given data to the texture. void Upload(const mjrTextureData& data); @@ -117,8 +119,12 @@ class Texture { return has_spherical_harmonics_ ? &spherical_harmonics_ : nullptr; } - Texture(const Texture&) = delete; - Texture& operator=(const Texture&) = delete; + static Texture* downcast(mjrTexture* texture) { + return static_cast(texture); + } + static const Texture* downcast(const mjrTexture* texture) { + return static_cast(texture); + } private: void ReleaseData(); diff --git a/src/experimental/filament/render_context_filament.h b/src/experimental/filament/render_context_filament.h index 28183fec..ef6f88ea 100644 --- a/src/experimental/filament/render_context_filament.h +++ b/src/experimental/filament/render_context_filament.h @@ -29,6 +29,17 @@ extern "C" { // IMPORTANT: This API should still be considered experimental and is likely // change frequently. +// Opaque types. +struct mjrTexture {}; +struct mjrMesh {}; +struct mjrScene {}; +struct mjrLight {}; +struct mjrRenderable {}; +struct mjrRenderTarget {}; + +// Opaque type for the filament rendering context. +struct mjrfContext {}; + typedef enum mjrGraphicsApi_ { // backend graphics API to use mjGRAPHICS_API_DEFAULT = 0, // default based on platform mjGRAPHICS_API_OPENGL, // OpenGL (desktop) / WebGL