// ---------------------------------------------------------------------------- // - Open3D: www.open3d.org - // ---------------------------------------------------------------------------- // Copyright (c) 2018-2023 www.open3d.org // SPDX-License-Identifier: MIT // ---------------------------------------------------------------------------- #pragma once #include #include #include #include #include namespace open3d { namespace visualization { namespace rendering { // If you add entry here, don't forget to update TypeToString! enum class EntityType : std::uint16_t { None = 0, View, Scene, Geometry, Light, IndirectLight, Skybox, Camera, Material, MaterialInstance, Texture, RenderTarget, VertexBuffer, IndexBuffer, Count }; // RenderEntityHandle - handle type for entities inside Renderer // Can be used in STL containers as key struct REHandle_abstract { static const char* TypeToString(EntityType type); static const std::uint16_t kBadId = 0; const EntityType type = EntityType::None; inline size_t Hash() const { return static_cast(type) << 16 | id; } bool operator==(const REHandle_abstract& other) const { return id == other.id && type == other.type; } bool operator!=(const REHandle_abstract& other) const { return !operator==(other); } bool operator<(const REHandle_abstract& other) const { return Hash() < other.Hash(); } explicit operator bool() const { return id != kBadId; } REHandle_abstract() : type(EntityType::None), id(kBadId) {} std::uint16_t GetId() const { return id; } protected: REHandle_abstract(const EntityType aType, const std::uint16_t aId) : type(aType), id(aId) {} static std::array(EntityType::Count)> uid_table; std::uint16_t id = kBadId; }; std::ostream& operator<<(std::ostream& os, const REHandle_abstract& uid); // REHandle is used for specification of handle types to prevent // errors with passing, assigning or comparison of different kinds of handles template struct REHandle : public REHandle_abstract { static const REHandle kBad; static REHandle Next() { const auto index = static_cast(entityType); auto id = ++uid_table[index]; if (id == REHandle_abstract::kBadId) { uid_table[index] = REHandle_abstract::kBadId + 1; id = REHandle_abstract::kBadId + 1; } return std::move(REHandle(id)); } static REHandle Concretize(const REHandle_abstract& abstract) { if (abstract.type != entityType) { // assert("Incompatible render uid types!\n"); return REHandle(); } return REHandle(abstract.GetId()); } REHandle() : REHandle_abstract(entityType, REHandle_abstract::kBadId) {} REHandle(const REHandle& other) : REHandle_abstract(entityType, other.id) {} // Don't use this constructor unless you know what you are doing explicit REHandle(std::uint16_t id) : REHandle_abstract(entityType, id) {} REHandle& operator=(const REHandle& other) { id = other.id; return *this; } }; template const REHandle REHandle::kBad; typedef REHandle ViewHandle; typedef REHandle SceneHandle; typedef REHandle GeometryHandle; typedef REHandle LightHandle; typedef REHandle IndirectLightHandle; typedef REHandle SkyboxHandle; typedef REHandle CameraHandle; typedef REHandle MaterialHandle; typedef REHandle MaterialInstanceHandle; typedef REHandle TextureHandle; typedef REHandle RenderTargetHandle; typedef REHandle VertexBufferHandle; typedef REHandle IndexBufferHandle; } // namespace rendering } // namespace visualization } // namespace open3d /// @cond namespace std { template <> class hash { public: size_t operator()(const open3d::visualization::rendering::REHandle_abstract& uid) const { return uid.Hash(); } }; } // namespace std namespace fmt { template struct formatter< T, std::enable_if_t::value, char>> { template auto format(const open3d::visualization::rendering::REHandle_abstract& uid, FormatContext& ctx) -> decltype(ctx.out()) { return format_to(ctx.out(), "[{}, {}, hash: {}]", open3d::visualization::rendering::REHandle_abstract:: TypeToString(uid.type), uid.GetId(), uid.Hash()); } template constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } }; } // namespace fmt /// @endcond