diff --git a/android/filament-android/src/main/cpp/Scene.cpp b/android/filament-android/src/main/cpp/Scene.cpp index 25e6be09ba4..b1d3d003489 100644 --- a/android/filament-android/src/main/cpp/Scene.cpp +++ b/android/filament-android/src/main/cpp/Scene.cpp @@ -71,6 +71,13 @@ Java_com_google_android_filament_Scene_nRemoveEntities(JNIEnv *env, jclass type, env->ReleaseIntArrayElements(entities, (jint*) nativeEntities, JNI_ABORT); } +extern "C" JNIEXPORT jint JNICALL +Java_com_google_android_filament_Scene_nGetEntityCount(JNIEnv *env, jclass type, + jlong nativeScene) { + Scene* scene = (Scene*) nativeScene; + return (jint) scene->getEntityCount(); +} + extern "C" JNIEXPORT jint JNICALL Java_com_google_android_filament_Scene_nGetRenderableCount(JNIEnv *env, jclass type, jlong nativeScene) { diff --git a/android/filament-android/src/main/java/com/google/android/filament/Scene.java b/android/filament-android/src/main/java/com/google/android/filament/Scene.java index 283b7024e73..fd425fbeaac 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/Scene.java +++ b/android/filament-android/src/main/java/com/google/android/filament/Scene.java @@ -146,18 +146,29 @@ public void removeEntities(@Entity int[] entities) { } /** - * Returns the number of {@link RenderableManager} components in the Scene. + * Returns the total number of Entities in the Scene, whether alive or not. * - * @return number of {@link RenderableManager} components in the Scene.. + * @return the total number of Entities in the Scene. + */ + public int getEntityCount() { + return nGetEntityCount(getNativeObject()); + } + + /** + * Returns the number of active (alive) {@link RenderableManager} components in the + * Scene. + * + * @return number of {@link RenderableManager} components in the Scene. */ public int getRenderableCount() { return nGetRenderableCount(getNativeObject()); } /** - * Returns the number of {@link LightManager} components in the Scene. + * Returns the number of active (alive) {@link LightManager} components in the + * Scene. * - * @return number of {@link LightManager} components in the Scene.. + * @return number of {@link LightManager} components in the Scene. */ public int getLightCount() { return nGetLightCount(getNativeObject()); @@ -189,6 +200,7 @@ void clearNativeObject() { private static native void nAddEntities(long nativeScene, int[] entities); private static native void nRemove(long nativeScene, int entity); private static native void nRemoveEntities(long nativeScene, int[] entities); + private static native int nGetEntityCount(long nativeScene); private static native int nGetRenderableCount(long nativeScene); private static native int nGetLightCount(long nativeScene); private static native boolean nHasEntity(long nativeScene, int entity); diff --git a/filament/include/filament/BufferObject.h b/filament/include/filament/BufferObject.h index 1ede31b8cb0..edabba83fa4 100644 --- a/filament/include/filament/BufferObject.h +++ b/filament/include/filament/BufferObject.h @@ -110,6 +110,10 @@ class UTILS_PUBLIC BufferObject : public FilamentAPI { * @return The maximum capacity of the BufferObject. */ size_t getByteCount() const noexcept; + +protected: + // prevent heap allocation + ~BufferObject() = default; }; } // namespace filament diff --git a/filament/include/filament/Camera.h b/filament/include/filament/Camera.h index 1c52a47cae6..ab06a413b58 100644 --- a/filament/include/filament/Camera.h +++ b/filament/include/filament/Camera.h @@ -565,6 +565,10 @@ class UTILS_PUBLIC Camera : public FilamentAPI { * @return effective full field of view in degrees */ static double computeEffectiveFov(double fovInDegrees, double focusDistance) noexcept; + +protected: + // prevent heap allocation + ~Camera() = default; }; } // namespace filament diff --git a/filament/include/filament/ColorGrading.h b/filament/include/filament/ColorGrading.h index db709600ef3..0cd4e8618a7 100644 --- a/filament/include/filament/ColorGrading.h +++ b/filament/include/filament/ColorGrading.h @@ -478,6 +478,10 @@ class UTILS_PUBLIC ColorGrading : public FilamentAPI { private: friend class FColorGrading; }; + +protected: + // prevent heap allocation + ~ColorGrading() = default; }; } // namespace filament diff --git a/filament/include/filament/DebugRegistry.h b/filament/include/filament/DebugRegistry.h index 3fa8c5a4326..f4df9e07a5d 100644 --- a/filament/include/filament/DebugRegistry.h +++ b/filament/include/filament/DebugRegistry.h @@ -142,6 +142,10 @@ class UTILS_PUBLIC DebugRegistry : public FilamentAPI { float pid_i = 0.0f; float pid_d = 0.0f; }; + +protected: + // prevent heap allocation + ~DebugRegistry() = default; }; diff --git a/filament/include/filament/Fence.h b/filament/include/filament/Fence.h index bcfd2871fd3..56cb33e66f2 100644 --- a/filament/include/filament/Fence.h +++ b/filament/include/filament/Fence.h @@ -75,6 +75,10 @@ class UTILS_PUBLIC Fence : public FilamentAPI { * FenceStatus::ERROR otherwise. */ static FenceStatus waitAndDestroy(Fence* fence, Mode mode = Mode::FLUSH); + +protected: + // prevent heap allocation + ~Fence() = default; }; } // namespace filament diff --git a/filament/include/filament/FilamentAPI.h b/filament/include/filament/FilamentAPI.h index 2925aca4a5c..19d6ba246a9 100644 --- a/filament/include/filament/FilamentAPI.h +++ b/filament/include/filament/FilamentAPI.h @@ -49,8 +49,6 @@ class UTILS_PUBLIC FilamentAPI { // prevent heap allocation static void *operator new (size_t) = delete; static void *operator new[] (size_t) = delete; - static void operator delete (void*) = delete; - static void operator delete[](void*) = delete; }; template diff --git a/filament/include/filament/IndexBuffer.h b/filament/include/filament/IndexBuffer.h index 09b479296d5..09e433a36dd 100644 --- a/filament/include/filament/IndexBuffer.h +++ b/filament/include/filament/IndexBuffer.h @@ -118,6 +118,10 @@ class UTILS_PUBLIC IndexBuffer : public FilamentAPI { * @return The number of indices the IndexBuffer holds. */ size_t getIndexCount() const noexcept; + +protected: + // prevent heap allocation + ~IndexBuffer() = default; }; } // namespace filament diff --git a/filament/include/filament/IndirectLight.h b/filament/include/filament/IndirectLight.h index 70448523b77..4c3c6e2c38e 100644 --- a/filament/include/filament/IndirectLight.h +++ b/filament/include/filament/IndirectLight.h @@ -342,6 +342,10 @@ class UTILS_PUBLIC IndirectLight : public FilamentAPI { /** @deprecated use static versions instead */ UTILS_DEPRECATED math::float4 getColorEstimate(math::float3 direction) const noexcept; + +protected: + // prevent heap allocation + ~IndirectLight() = default; }; } // namespace filament diff --git a/filament/include/filament/InstanceBuffer.h b/filament/include/filament/InstanceBuffer.h index d1ad29a9088..671114a93f1 100644 --- a/filament/include/filament/InstanceBuffer.h +++ b/filament/include/filament/InstanceBuffer.h @@ -91,6 +91,10 @@ class UTILS_PUBLIC InstanceBuffer : public FilamentAPI { * @param offset index of the first instance to set local transforms */ void setLocalTransforms(math::mat4f const* localTransforms, size_t count, size_t offset = 0); + +protected: + // prevent heap allocation + ~InstanceBuffer() = default; }; } // namespace filament diff --git a/filament/include/filament/LightManager.h b/filament/include/filament/LightManager.h index b7cb62e16a1..fa0bdee71c8 100644 --- a/filament/include/filament/LightManager.h +++ b/filament/include/filament/LightManager.h @@ -143,20 +143,13 @@ class UTILS_PUBLIC LightManager : public FilamentAPI { using Instance = utils::EntityInstance; /** - * Returns the number of component in the LightManager, not that component are not + * Returns the number of component in the LightManager, note that component are not * guaranteed to be active. Use the EntityManager::isAlive() before use if needed. * * @return number of component in the LightManager */ size_t getComponentCount() const noexcept; - /** - * Returns the list of Entity for all components. Use getComponentCount() to know the size - * of the list. - * @return a pointer to Entity - */ - utils::Entity const* getEntities() const noexcept; - /** * Returns whether a particular Entity is associated with a component of this LightManager * @param e An Entity. @@ -164,6 +157,24 @@ class UTILS_PUBLIC LightManager : public FilamentAPI { */ bool hasComponent(utils::Entity e) const noexcept; + /** + * @return true if the this manager has no components + */ + bool empty() const noexcept; + + /** + * Retrieve the `Entity` of the component from its `Instance`. + * @param i Instance of the component obtained from getInstance() + * @return + */ + utils::Entity getEntity(Instance i) const noexcept; + + /** + * Retrieve the Entities of all the components of this manager. + * @return A list, in no particular order, of all the entities managed by this manager. + */ + utils::Entity const* getEntities() const noexcept; + /** * Gets an Instance representing the Light component associated with the given Entity. * @param e An Entity. @@ -953,19 +964,9 @@ class UTILS_PUBLIC LightManager : public FilamentAPI { */ bool isShadowCaster(Instance i) const noexcept; - /** - * Helper to process all components with a given function - * @tparam F a void(Entity entity, Instance instance) - * @param func a function of type F - */ - template - void forEachComponent(F func) noexcept { - utils::Entity const* const pEntity = getEntities(); - for (size_t i = 0, c = getComponentCount(); i < c; i++) { - // Instance 0 is the invalid instance - func(pEntity[i], Instance(i + 1)); - } - } +protected: + // prevent heap allocation + ~LightManager() = default; }; } // namespace filament diff --git a/filament/include/filament/Material.h b/filament/include/filament/Material.h index 123d8599f89..e6f374be910 100644 --- a/filament/include/filament/Material.h +++ b/filament/include/filament/Material.h @@ -375,6 +375,10 @@ class UTILS_PUBLIC Material : public FilamentAPI { //! Returns this material's default instance. MaterialInstance const* getDefaultInstance() const noexcept; + +protected: + // prevent heap allocation + ~Material() = default; }; } // namespace filament diff --git a/filament/include/filament/MaterialInstance.h b/filament/include/filament/MaterialInstance.h index ee7a8e252ff..0c6ef205730 100644 --- a/filament/include/filament/MaterialInstance.h +++ b/filament/include/filament/MaterialInstance.h @@ -479,6 +479,10 @@ class UTILS_PUBLIC MaterialInstance : public FilamentAPI { */ void setStencilWriteMask(uint8_t writeMask, StencilFace face = StencilFace::FRONT_AND_BACK) noexcept; + +protected: + // prevent heap allocation + ~MaterialInstance() = default; }; } // namespace filament diff --git a/filament/include/filament/MorphTargetBuffer.h b/filament/include/filament/MorphTargetBuffer.h index d080d0da674..e94854643e1 100644 --- a/filament/include/filament/MorphTargetBuffer.h +++ b/filament/include/filament/MorphTargetBuffer.h @@ -136,6 +136,10 @@ class UTILS_PUBLIC MorphTargetBuffer : public FilamentAPI { * @return The number of targets the MorphTargetBuffer holds. */ size_t getCount() const noexcept; + +protected: + // prevent heap allocation + ~MorphTargetBuffer() = default; }; } // namespace filament diff --git a/filament/include/filament/RenderTarget.h b/filament/include/filament/RenderTarget.h index 508e1c246f2..faeee80cf6e 100644 --- a/filament/include/filament/RenderTarget.h +++ b/filament/include/filament/RenderTarget.h @@ -180,6 +180,10 @@ class UTILS_PUBLIC RenderTarget : public FilamentAPI { * @return Number of color attachments usable in a render target. */ uint8_t getSupportedColorAttachmentsCount() const noexcept; + +protected: + // prevent heap allocation + ~RenderTarget() = default; }; } // namespace filament diff --git a/filament/include/filament/RenderableManager.h b/filament/include/filament/RenderableManager.h index 30705b8d62f..8383a94748f 100644 --- a/filament/include/filament/RenderableManager.h +++ b/filament/include/filament/RenderableManager.h @@ -102,6 +102,29 @@ class UTILS_PUBLIC RenderableManager : public FilamentAPI { */ Instance getInstance(utils::Entity e) const noexcept; + /** + * @return the number of Components + */ + size_t getComponentCount() const noexcept; + + /** + * @return true if the this manager has no components + */ + bool empty() const noexcept; + + /** + * Retrieve the `Entity` of the component from its `Instance`. + * @param i Instance of the component obtained from getInstance() + * @return + */ + utils::Entity getEntity(Instance i) const noexcept; + + /** + * Retrieve the Entities of all the components of this manager. + * @return A list, in no particular order, of all the entities managed by this manager. + */ + utils::Entity const* getEntities() const noexcept; + /** * The transformation associated with a skinning joint. * @@ -829,6 +852,10 @@ class UTILS_PUBLIC RenderableManager : public FilamentAPI { typename = typename is_supported_index_type::type> static Box computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count, size_t stride = sizeof(VECTOR)) noexcept; + +protected: + // prevent heap allocation + ~RenderableManager() = default; }; RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t level, size_t primitiveIndex, diff --git a/filament/include/filament/Renderer.h b/filament/include/filament/Renderer.h index 999f31a9652..8295a06fed3 100644 --- a/filament/include/filament/Renderer.h +++ b/filament/include/filament/Renderer.h @@ -579,6 +579,10 @@ class UTILS_PUBLIC Renderer : public FilamentAPI { * getUserTime() */ void resetUserTime(); + +protected: + // prevent heap allocation + ~Renderer() = default; }; } // namespace filament diff --git a/filament/include/filament/Scene.h b/filament/include/filament/Scene.h index 3e6a63c4b3f..28361278a2f 100644 --- a/filament/include/filament/Scene.h +++ b/filament/include/filament/Scene.h @@ -140,16 +140,22 @@ class UTILS_PUBLIC Scene : public FilamentAPI { void removeEntities(const utils::Entity* entities, size_t count); /** - * Returns the number of Renderable objects in the Scene. + * Returns the total number of Entities in the Scene, whether alive or not. + * @return Total number of Entities in the Scene. + */ + size_t getEntityCount() const noexcept; + + /** + * Returns the number of active (alive) Renderable objects in the Scene. * - * @return number of Renderable objects in the Scene. + * @return The number of active (alive) Renderable objects in the Scene. */ size_t getRenderableCount() const noexcept; /** - * Returns the total number of Light objects in the Scene. + * Returns the number of active (alive) Light objects in the Scene. * - * @return The total number of Light objects in the Scene. + * @return The number of active (alive) Light objects in the Scene. */ size_t getLightCount() const noexcept; @@ -168,6 +174,10 @@ class UTILS_PUBLIC Scene : public FilamentAPI { * @param functor User provided functor called for each entity in the scene */ void forEach(utils::Invocable&& functor) const noexcept; + +protected: + // prevent heap allocation + ~Scene() = default; }; } // namespace filament diff --git a/filament/include/filament/SkinningBuffer.h b/filament/include/filament/SkinningBuffer.h index 007feb85085..5c334563602 100644 --- a/filament/include/filament/SkinningBuffer.h +++ b/filament/include/filament/SkinningBuffer.h @@ -115,6 +115,10 @@ class UTILS_PUBLIC SkinningBuffer : public FilamentAPI { * @return The number of bones the SkinningBuffer holds. */ size_t getBoneCount() const noexcept; + +protected: + // prevent heap allocation + ~SkinningBuffer() = default; }; } // namespace filament diff --git a/filament/include/filament/Skybox.h b/filament/include/filament/Skybox.h index 5e9f2c60636..150c9d3e4cf 100644 --- a/filament/include/filament/Skybox.h +++ b/filament/include/filament/Skybox.h @@ -174,6 +174,10 @@ class UTILS_PUBLIC Skybox : public FilamentAPI { * @return the associated texture, or null if it does not exist */ Texture const* getTexture() const noexcept; + +protected: + // prevent heap allocation + ~Skybox() = default; }; } // namespace filament diff --git a/filament/include/filament/Stream.h b/filament/include/filament/Stream.h index 7fccecfe3ee..83f898acae2 100644 --- a/filament/include/filament/Stream.h +++ b/filament/include/filament/Stream.h @@ -207,6 +207,10 @@ class UTILS_PUBLIC Stream : public FilamentAPI { * @return timestamp in nanosecond. */ int64_t getTimestamp() const noexcept; + +protected: + // prevent heap allocation + ~Stream() = default; }; } // namespace filament diff --git a/filament/include/filament/SwapChain.h b/filament/include/filament/SwapChain.h index 26c3da4a04d..c17523acd5d 100644 --- a/filament/include/filament/SwapChain.h +++ b/filament/include/filament/SwapChain.h @@ -286,6 +286,10 @@ class UTILS_PUBLIC SwapChain : public FilamentAPI { void setFrameCompletedCallback(backend::CallbackHandler* handler = nullptr, FrameCompletedCallback&& callback = {}) noexcept; + +protected: + // prevent heap allocation + ~SwapChain() = default; }; } // namespace filament diff --git a/filament/include/filament/Texture.h b/filament/include/filament/Texture.h index c005c2b165e..bb011cc9781 100644 --- a/filament/include/filament/Texture.h +++ b/filament/include/filament/Texture.h @@ -541,6 +541,10 @@ class UTILS_PUBLIC Texture : public FilamentAPI { return *this; } }; + +protected: + // prevent heap allocation + ~Texture() = default; }; } // namespace filament diff --git a/filament/include/filament/TransformManager.h b/filament/include/filament/TransformManager.h index 9afa6897128..73ac2c99005 100644 --- a/filament/include/filament/TransformManager.h +++ b/filament/include/filament/TransformManager.h @@ -118,6 +118,29 @@ class UTILS_PUBLIC TransformManager : public FilamentAPI { */ Instance getInstance(utils::Entity e) const noexcept; + /** + * @return the number of Components + */ + size_t getComponentCount() const noexcept; + + /** + * @return true if the this manager has no components + */ + bool empty() const noexcept; + + /** + * Retrieve the `Entity` of the component from its `Instance`. + * @param i Instance of the component obtained from getInstance() + * @return + */ + utils::Entity getEntity(Instance i) const noexcept; + + /** + * Retrieve the Entities of all the components of this manager. + * @return A list, in no particular order, of all the entities managed by this manager. + */ + utils::Entity const* getEntities() const noexcept; + /** * Enables or disable the accurate translation mode. Disabled by default. * @@ -261,7 +284,7 @@ class UTILS_PUBLIC TransformManager : public FilamentAPI { * returns the value set by setTransform(). * @see setTransform() */ - const math::mat4 getTransformAccurate(Instance ci) const noexcept; + math::mat4 getTransformAccurate(Instance ci) const noexcept; /** * Return the world transform of a transform component. @@ -279,7 +302,7 @@ class UTILS_PUBLIC TransformManager : public FilamentAPI { * composition of this component's local transform with its parent's world transform. * @see setTransform() */ - const math::mat4 getWorldTransformAccurate(Instance ci) const noexcept; + math::mat4 getWorldTransformAccurate(Instance ci) const noexcept; /** * Opens a local transform transaction. During a transaction, getWorldTransform() can @@ -308,6 +331,10 @@ class UTILS_PUBLIC TransformManager : public FilamentAPI { * @see openLocalTransformTransaction(), setTransform() */ void commitLocalTransformTransaction() noexcept; + +protected: + // prevent heap allocation + ~TransformManager() = default; }; } // namespace filament diff --git a/filament/include/filament/VertexBuffer.h b/filament/include/filament/VertexBuffer.h index dd844c375a0..317d5a7368a 100644 --- a/filament/include/filament/VertexBuffer.h +++ b/filament/include/filament/VertexBuffer.h @@ -207,6 +207,10 @@ class UTILS_PUBLIC VertexBuffer : public FilamentAPI { * @param bufferObject The handle to the GPU data that will be used in this buffer slot. */ void setBufferObjectAt(Engine& engine, uint8_t bufferIndex, BufferObject const* bufferObject); + +protected: + // prevent heap allocation + ~VertexBuffer() = default; }; } // namespace filament diff --git a/filament/include/filament/View.h b/filament/include/filament/View.h index 4bba745d1f3..5eddb99143b 100644 --- a/filament/include/filament/View.h +++ b/filament/include/filament/View.h @@ -894,6 +894,10 @@ class UTILS_PUBLIC View : public FilamentAPI { */ UTILS_DEPRECATED AmbientOcclusion getAmbientOcclusion() const noexcept; + +protected: + // prevent heap allocation + ~View() = default; }; } // namespace filament diff --git a/filament/src/LightManager.cpp b/filament/src/LightManager.cpp index be0252c1230..cc6bd083e55 100644 --- a/filament/src/LightManager.cpp +++ b/filament/src/LightManager.cpp @@ -22,16 +22,24 @@ namespace filament { using namespace math; +bool LightManager::hasComponent(Entity e) const noexcept { + return downcast(this)->hasComponent(e); +} + size_t LightManager::getComponentCount() const noexcept { return downcast(this)->getComponentCount(); } -utils::Entity const* LightManager::getEntities() const noexcept { - return downcast(this)->getEntities(); +bool LightManager::empty() const noexcept { + return downcast(this)->empty(); } -bool LightManager::hasComponent(Entity e) const noexcept { - return downcast(this)->hasComponent(e); +utils::Entity LightManager::getEntity(LightManager::Instance i) const noexcept { + return downcast(this)->getEntity(i); +} + +utils::Entity const* LightManager::getEntities() const noexcept { + return downcast(this)->getEntities(); } LightManager::Instance LightManager::getInstance(Entity e) const noexcept { diff --git a/filament/src/RenderableManager.cpp b/filament/src/RenderableManager.cpp index bc1240415d1..71a83bf544c 100644 --- a/filament/src/RenderableManager.cpp +++ b/filament/src/RenderableManager.cpp @@ -31,6 +31,22 @@ bool RenderableManager::hasComponent(utils::Entity e) const noexcept { return downcast(this)->hasComponent(e); } +size_t RenderableManager::getComponentCount() const noexcept { + return downcast(this)->getComponentCount(); +} + +bool RenderableManager::empty() const noexcept { + return downcast(this)->empty(); +} + +utils::Entity RenderableManager::getEntity(RenderableManager::Instance i) const noexcept { + return downcast(this)->getEntity(i); +} + +utils::Entity const* RenderableManager::getEntities() const noexcept { + return downcast(this)->getEntities(); +} + RenderableManager::Instance RenderableManager::getInstance(utils::Entity e) const noexcept { return downcast(this)->getInstance(e); diff --git a/filament/src/Scene.cpp b/filament/src/Scene.cpp index e686824ed91..1cc7496723f 100644 --- a/filament/src/Scene.cpp +++ b/filament/src/Scene.cpp @@ -55,6 +55,10 @@ void Scene::removeEntities(const Entity* entities, size_t count) { downcast(this)->removeEntities(entities, count); } +size_t Scene::getEntityCount() const noexcept { + return downcast(this)->getEntityCount(); +} + size_t Scene::getRenderableCount() const noexcept { return downcast(this)->getRenderableCount(); } diff --git a/filament/src/TransformManager.cpp b/filament/src/TransformManager.cpp index 4a6b672fe75..384b930c506 100644 --- a/filament/src/TransformManager.cpp +++ b/filament/src/TransformManager.cpp @@ -22,6 +22,30 @@ namespace filament { using namespace math; +bool TransformManager::hasComponent(Entity e) const noexcept { + return downcast(this)->hasComponent(e); +} + +size_t TransformManager::getComponentCount() const noexcept { + return downcast(this)->getComponentCount(); +} + +bool TransformManager::empty() const noexcept { + return downcast(this)->empty(); +} + +utils::Entity TransformManager::getEntity(TransformManager::Instance i) const noexcept { + return downcast(this)->getEntity(i); +} + +utils::Entity const* TransformManager::getEntities() const noexcept { + return downcast(this)->getEntities(); +} + +TransformManager::Instance TransformManager::getInstance(Entity e) const noexcept { + return downcast(this)->getInstance(e); +} + void TransformManager::create(Entity entity, Instance parent, const mat4f& worldTransform) { downcast(this)->create(entity, parent, worldTransform); } @@ -38,14 +62,6 @@ void TransformManager::destroy(Entity e) noexcept { downcast(this)->destroy(e); } -bool TransformManager::hasComponent(Entity e) const noexcept { - return downcast(this)->hasComponent(e); -} - -TransformManager::Instance TransformManager::getInstance(Entity e) const noexcept { - return downcast(this)->getInstance(e); -} - void TransformManager::setTransform(Instance ci, const mat4f& model) noexcept { downcast(this)->setTransform(ci, model); } @@ -58,7 +74,7 @@ const mat4f& TransformManager::getTransform(Instance ci) const noexcept { return downcast(this)->getTransform(ci); } -const mat4 TransformManager::getTransformAccurate(Instance ci) const noexcept { +mat4 TransformManager::getTransformAccurate(Instance ci) const noexcept { return downcast(this)->getTransformAccurate(ci); } @@ -66,7 +82,7 @@ const mat4f& TransformManager::getWorldTransform(Instance ci) const noexcept { return downcast(this)->getWorldTransform(ci); } -const mat4 TransformManager::getWorldTransformAccurate(Instance ci) const noexcept { +mat4 TransformManager::getWorldTransformAccurate(Instance ci) const noexcept { return downcast(this)->getWorldTransformAccurate(ci); } @@ -110,7 +126,7 @@ void TransformManager::setAccurateTranslationsEnabled(bool enable) noexcept { } bool TransformManager::isAccurateTranslationsEnabled() const noexcept { - return downcast(this)->isAccurateTranslationsEnabled();; + return downcast(this)->isAccurateTranslationsEnabled(); } } // namespace filament diff --git a/filament/src/components/CameraManager.cpp b/filament/src/components/CameraManager.cpp index a34b376d48f..b48742eae6c 100644 --- a/filament/src/components/CameraManager.cpp +++ b/filament/src/components/CameraManager.cpp @@ -49,7 +49,7 @@ void FCameraManager::terminate(FEngine& engine) noexcept { void FCameraManager::gc(FEngine& engine, utils::EntityManager& em) noexcept { auto& manager = mManager; - manager.gc(em, 4, [this, &engine](Entity e) { + manager.gc(em, [this, &engine](Entity e) { destroy(engine, e); }); } diff --git a/filament/src/components/CameraManager.h b/filament/src/components/CameraManager.h index 239790a3990..67bbfcb9aed 100644 --- a/filament/src/components/CameraManager.h +++ b/filament/src/components/CameraManager.h @@ -57,7 +57,23 @@ class UTILS_PRIVATE FCameraManager : public CameraManager { } Instance getInstance(utils::Entity e) const noexcept { - return Instance(mManager.getInstance(e)); + return { mManager.getInstance(e) }; + } + + size_t getComponentCount() const noexcept { + return mManager.getComponentCount(); + } + + bool empty() const noexcept { + return mManager.empty(); + } + + utils::Entity getEntity(Instance i) const noexcept { + return mManager.getEntity(i); + } + + utils::Entity const* getEntities() const noexcept { + return mManager.getEntities(); } FCamera* getCamera(Instance i) noexcept { diff --git a/filament/src/components/LightManager.cpp b/filament/src/components/LightManager.cpp index 76e2beea67c..6393caa10aa 100644 --- a/filament/src/components/LightManager.cpp +++ b/filament/src/components/LightManager.cpp @@ -227,7 +227,9 @@ void FLightManager::terminate() noexcept { } } void FLightManager::gc(utils::EntityManager& em) noexcept { - mManager.gc(em); + mManager.gc(em, [this](Entity e) { + destroy(e); + }); } void FLightManager::setShadowOptions(Instance i, ShadowOptions const& options) noexcept { diff --git a/filament/src/components/LightManager.h b/filament/src/components/LightManager.h index 47f5cfcc275..317ec723f72 100644 --- a/filament/src/components/LightManager.h +++ b/filament/src/components/LightManager.h @@ -46,20 +46,32 @@ class FLightManager : public LightManager { void gc(utils::EntityManager& em) noexcept; + /* + * Component Manager APIs + */ + + bool hasComponent(utils::Entity e) const noexcept { + return mManager.hasComponent(e); + } + + Instance getInstance(utils::Entity e) const noexcept { + return { mManager.getInstance(e) }; + } + size_t getComponentCount() const noexcept { return mManager.getComponentCount(); } - utils::Entity const* getEntities() const noexcept { - return mManager.getEntities(); + bool empty() const noexcept { + return mManager.empty(); } - bool hasComponent(utils::Entity e) const noexcept { - return mManager.hasComponent(e); + utils::Entity getEntity(Instance i) const noexcept { + return mManager.getEntity(i); } - Instance getInstance(utils::Entity e) const noexcept { - return mManager.getInstance(e); + utils::Entity const* getEntities() const noexcept { + return mManager.getEntities(); } void create(const FLightManager::Builder& builder, utils::Entity entity); diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp index d43fdb59d58..11e4eba8f5b 100644 --- a/filament/src/components/RenderableManager.cpp +++ b/filament/src/components/RenderableManager.cpp @@ -678,7 +678,9 @@ void FRenderableManager::terminate() noexcept { } void FRenderableManager::gc(utils::EntityManager& em) noexcept { - mManager.gc(em); + mManager.gc(em, [this](Entity e) { + destroy(e); + }); } // This is basically a Renderable's destructor. diff --git a/filament/src/components/RenderableManager.h b/filament/src/components/RenderableManager.h index d79d2ca3eeb..746c46dbeee 100644 --- a/filament/src/components/RenderableManager.h +++ b/filament/src/components/RenderableManager.h @@ -92,7 +92,23 @@ class FRenderableManager : public RenderableManager { } Instance getInstance(utils::Entity e) const noexcept { - return mManager.getInstance(e); + return { mManager.getInstance(e) }; + } + + size_t getComponentCount() const noexcept { + return mManager.getComponentCount(); + } + + bool empty() const noexcept { + return mManager.empty(); + } + + utils::Entity getEntity(Instance i) const noexcept { + return mManager.getEntity(i); + } + + utils::Entity const* getEntities() const noexcept { + return mManager.getEntities(); } void create(const RenderableManager::Builder& builder, utils::Entity entity); @@ -176,10 +192,6 @@ class FRenderableManager : public RenderableManager { static_assert(sizeof(InstancesInfo) == 16); inline InstancesInfo getInstancesInfo(Instance instance) const noexcept; - utils::Entity getEntity(Instance instance) const noexcept { - return mManager.getEntity(instance); - } - inline size_t getLevelCount(Instance) const noexcept { return 1u; } size_t getPrimitiveCount(Instance instance, uint8_t level) const noexcept; void setMaterialInstanceAt(Instance instance, uint8_t level, diff --git a/filament/src/components/TransformManager.cpp b/filament/src/components/TransformManager.cpp index 9324d5ac6ed..7806e41f02e 100644 --- a/filament/src/components/TransformManager.cpp +++ b/filament/src/components/TransformManager.cpp @@ -471,8 +471,7 @@ void FTransformManager::validateNode(UTILS_UNUSED_IN_RELEASE Instance i) noexcep } void FTransformManager::gc(utils::EntityManager& em) noexcept { - auto& manager = mManager; - manager.gc(em, 4, [this](Entity e) { + mManager.gc(em, [this](Entity e) { destroy(e); }); } diff --git a/filament/src/components/TransformManager.h b/filament/src/components/TransformManager.h index e7a674c8b0e..6e42103370c 100644 --- a/filament/src/components/TransformManager.h +++ b/filament/src/components/TransformManager.h @@ -50,7 +50,23 @@ class UTILS_PRIVATE FTransformManager : public TransformManager { } Instance getInstance(utils::Entity e) const noexcept { - return Instance(mManager.getInstance(e)); + return { mManager.getInstance(e) }; + } + + size_t getComponentCount() const noexcept { + return mManager.getComponentCount(); + } + + bool empty() const noexcept { + return mManager.empty(); + } + + utils::Entity getEntity(Instance i) const noexcept { + return mManager.getEntity(i); + } + + utils::Entity const* getEntities() const noexcept { + return mManager.getEntities(); } void setAccurateTranslationsEnabled(bool enable) noexcept; @@ -103,7 +119,7 @@ class UTILS_PRIVATE FTransformManager : public TransformManager { math::mat4 getTransformAccurate(Instance ci) const noexcept { math::mat4f const& local = mManager[ci].local; - math::float3 localTranslationLo = mManager[ci].localTranslationLo; + math::float3 const localTranslationLo = mManager[ci].localTranslationLo; math::mat4 r(local); r[3].xyz += localTranslationLo; return r; @@ -111,7 +127,7 @@ class UTILS_PRIVATE FTransformManager : public TransformManager { math::mat4 getWorldTransformAccurate(Instance ci) const noexcept { math::mat4f const& world = mManager[ci].world; - math::float3 worldTranslationLo = mManager[ci].worldTranslationLo; + math::float3 const worldTranslationLo = mManager[ci].worldTranslationLo; math::mat4 r(world); r[3].xyz += worldTranslationLo; return r; diff --git a/filament/src/details/Scene.h b/filament/src/details/Scene.h index 2e0aff2ae8b..1882bb4dc30 100644 --- a/filament/src/details/Scene.h +++ b/filament/src/details/Scene.h @@ -55,7 +55,7 @@ class FSkybox; class FScene : public Scene { public: /* - * Filaments-scope Public API + * Filament-scope Public API */ FSkybox* getSkybox() const noexcept { return mSkybox; } @@ -197,6 +197,7 @@ class FScene : public Scene { void addEntities(const utils::Entity* entities, size_t count); void remove(utils::Entity entity); void removeEntities(const utils::Entity* entities, size_t count); + size_t getEntityCount() const noexcept { return mEntities.size(); } size_t getRenderableCount() const noexcept; size_t getLightCount() const noexcept; bool hasEntity(utils::Entity entity) const noexcept; diff --git a/libs/gltfio/src/FNodeManager.h b/libs/gltfio/src/FNodeManager.h index 5f8dc53edb7..4e1c80d8877 100644 --- a/libs/gltfio/src/FNodeManager.h +++ b/libs/gltfio/src/FNodeManager.h @@ -57,13 +57,15 @@ class UTILS_PRIVATE FNodeManager : public NodeManager { } void destroy(utils::Entity e) noexcept { - if (Instance ci = mManager.getInstance(e); ci) { + if (Instance const ci = mManager.getInstance(e); ci) { mManager.removeComponent(e); } } void gc(utils::EntityManager& em) noexcept { - mManager.gc(em); + mManager.gc(em, [this](Entity e) { + destroy(e); + }); } void setMorphTargetNames(Instance ci, utils::FixedCapacityVector names) noexcept { diff --git a/libs/gltfio/src/FTrsTransformManager.h b/libs/gltfio/src/FTrsTransformManager.h index c53342fcdb6..a2cb53e06e5 100644 --- a/libs/gltfio/src/FTrsTransformManager.h +++ b/libs/gltfio/src/FTrsTransformManager.h @@ -70,13 +70,15 @@ class UTILS_PRIVATE FTrsTransformManager : public TrsTransformManager { } void destroy(utils::Entity e) noexcept { - if (Instance ci = mManager.getInstance(e); ci) { + if (Instance const ci = mManager.getInstance(e); ci) { mManager.removeComponent(e); } } void gc(utils::EntityManager& em) noexcept { - mManager.gc(em); + mManager.gc(em, [this](Entity e) { + destroy(e); + }); } void setTranslation(Instance ci, const float3& translation) noexcept { diff --git a/libs/utils/include/utils/EntityManager.h b/libs/utils/include/utils/EntityManager.h index 9674cac2554..8fac30cc532 100644 --- a/libs/utils/include/utils/EntityManager.h +++ b/libs/utils/include/utils/EntityManager.h @@ -44,23 +44,25 @@ class UTILS_PUBLIC EntityManager { public: virtual void onEntitiesDestroyed(size_t n, Entity const* entities) noexcept = 0; protected: - ~Listener() noexcept; + virtual ~Listener() noexcept; }; - // maximum number of entities that can exist at the same time static size_t getMaxEntityCount() noexcept { // because index 0 is reserved, we only have 2^GENERATION_SHIFT - 1 valid indices return RAW_INDEX_COUNT - 1; } - // create n entities. Thread safe. + // number of active Entities + size_t getEntityCount() const noexcept; + + // Create n entities. Thread safe. void create(size_t n, Entity* entities); // destroys n entities. Thread safe. void destroy(size_t n, Entity* entities) noexcept; - // create a new Entity. Thread safe. + // Create a new Entity. Thread safe. // Return Entity.isNull() if the entity cannot be allocated. Entity create() { Entity e; @@ -68,20 +70,20 @@ class UTILS_PUBLIC EntityManager { return e; } - // destroys an Entity. Thread safe. + // Destroys an Entity. Thread safe. void destroy(Entity e) noexcept { destroy(1, &e); } - // return whether the given Entity has been destroyed (false) or not (true). + // Return whether the given Entity has been destroyed (false) or not (true). // Thread safe. bool isAlive(Entity e) const noexcept { assert(getIndex(e) < RAW_INDEX_COUNT); return (!e.isNull()) && (getGeneration(e) == mGens[getIndex(e)]); } - // registers a listener to be called when an entity is destroyed. thread safe. - // if the listener is already register, this method has no effect. + // Registers a listener to be called when an entity is destroyed. Thread safe. + // If the listener is already registered, this method has no effect. void registerListener(Listener* l) noexcept; // unregisters a listener. @@ -94,6 +96,7 @@ class UTILS_PUBLIC EntityManager { uint8_t getGenerationForIndex(size_t index) const noexcept { return mGens[index]; } + // singleton, can't be copied EntityManager(const EntityManager& rhs) = delete; EntityManager& operator=(const EntityManager& rhs) = delete; diff --git a/libs/utils/include/utils/NameComponentManager.h b/libs/utils/include/utils/NameComponentManager.h index 9e31e4618de..a161b56ad74 100644 --- a/libs/utils/include/utils/NameComponentManager.h +++ b/libs/utils/include/utils/NameComponentManager.h @@ -48,7 +48,7 @@ class EntityManager; * printf("%s\n", names->getName(names->getInstance(myEntity)); * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -class UTILS_PUBLIC NameComponentManager : public SingleInstanceComponentManager { +class UTILS_PUBLIC NameComponentManager : private SingleInstanceComponentManager { public: using Instance = EntityInstance; @@ -75,15 +75,6 @@ class UTILS_PUBLIC NameComponentManager : public SingleInstanceComponentManager< return { SingleInstanceComponentManager::getInstance(e) }; } - /*! \cond PRIVATE */ - // these are implemented in SingleInstanceComponentManager<>, but we need to - // reimplement them in each manager, to ensure they are generated in an implementation file - // for backward binary compatibility reasons. - size_t getComponentCount() const noexcept; - Entity const* getEntities() const noexcept; - void gc(const EntityManager& em, size_t ratio = 4) noexcept; - /*! \endcond */ - /** * Adds a name component to the given entity if it doesn't already exist. */ @@ -105,6 +96,12 @@ class UTILS_PUBLIC NameComponentManager : public SingleInstanceComponentManager< * @return pointer to the copy that was made during setName() */ const char* getName(Instance instance) const noexcept; + + void gc(EntityManager& em) noexcept { + SingleInstanceComponentManager::gc(em, [this](Entity e) { + removeComponent(e); + }); + } }; } // namespace utils diff --git a/libs/utils/include/utils/SingleInstanceComponentManager.h b/libs/utils/include/utils/SingleInstanceComponentManager.h index c03ec5f100c..ddd538f5e9f 100644 --- a/libs/utils/include/utils/SingleInstanceComponentManager.h +++ b/libs/utils/include/utils/SingleInstanceComponentManager.h @@ -98,7 +98,7 @@ class UTILS_PUBLIC SingleInstanceComponentManager { return pos != map.end() ? pos->second : 0; } - // returns the number of components (i.e. size of each arrays) + // Returns the number of components (i.e. size of each array) size_t getComponentCount() const noexcept { // The array as an extra dummy component at index 0, so the visible count is 1 less. return mData.size() - 1; @@ -108,11 +108,8 @@ class UTILS_PUBLIC SingleInstanceComponentManager { return getComponentCount() == 0; } - // returns a pointer to the Entity array. This is basically the list - // of entities this component manager handles. - // The pointer becomes invalid when adding or removing a component. - Entity const* getEntities() const noexcept { - return begin(); + utils::Entity const* getEntities() const noexcept { + return data() + 1; } Entity getEntity(Instance i) const noexcept { @@ -128,14 +125,6 @@ class UTILS_PUBLIC SingleInstanceComponentManager { // This invalidates all pointers components. inline Instance removeComponent(Entity e); - // trigger one round of garbage collection. this is intended to be called on a regular - // basis. This gc gives up after it cannot randomly free 'ratio' component in a row. - void gc(const EntityManager& em, size_t ratio = 4) noexcept { - gc(em, ratio, [this](Entity e) { - removeComponent(e); - }); - } - // return the first instance Instance begin() const noexcept { return 1u; } @@ -234,24 +223,33 @@ class UTILS_PUBLIC SingleInstanceComponentManager { } } + template + void gc(const EntityManager& em, + REMOVE&& removeComponent) noexcept { + gc(em, 4, std::forward(removeComponent)); + } + template void gc(const EntityManager& em, size_t ratio, - REMOVE removeComponent) noexcept { - Entity const* entities = getEntities(); + REMOVE&& removeComponent) noexcept { + Entity const* const pEntities = begin(); size_t count = getComponentCount(); size_t aliveInARow = 0; default_random_engine& rng = mRng; UTILS_NOUNROLL while (count && aliveInARow < ratio) { + assert_invariant(count == getComponentCount()); // note: using the modulo favorizes lower number - size_t i = rng() % count; - if (UTILS_LIKELY(em.isAlive(entities[i]))) { + size_t const i = rng() % count; + Entity const entity = pEntities[i]; + assert_invariant(entity); + if (UTILS_LIKELY(em.isAlive(entity))) { ++aliveInARow; continue; } + removeComponent(entity); aliveInARow = 0; count--; - removeComponent(entities[i]); } } diff --git a/libs/utils/src/EntityManager.cpp b/libs/utils/src/EntityManager.cpp index 30149c68ade..bdb12db3252 100644 --- a/libs/utils/src/EntityManager.cpp +++ b/libs/utils/src/EntityManager.cpp @@ -22,6 +22,8 @@ namespace utils { +EntityManager::Listener::~Listener() noexcept = default; + EntityManager::EntityManager() : mGens(new uint8_t[RAW_INDEX_COUNT]) { // initialize all the generations to 0 @@ -32,8 +34,6 @@ EntityManager::~EntityManager() { delete [] mGens; } -EntityManager::Listener::~Listener() noexcept = default; - EntityManager& EntityManager::get() noexcept { // note: we leak the EntityManager because it's more important that it survives everything else // the leak is really not a problem because the process is terminating anyway. @@ -57,6 +57,10 @@ void EntityManager::unregisterListener(EntityManager::Listener* l) noexcept { static_cast(this)->unregisterListener(l); } +size_t EntityManager::getEntityCount() const noexcept { + return static_cast(this)->getEntityCount(); +} + #if FILAMENT_UTILS_TRACK_ENTITIES std::vector EntityManager::getActiveEntities() const { return static_cast(this)->getActiveEntities(); diff --git a/libs/utils/src/EntityManagerImpl.h b/libs/utils/src/EntityManagerImpl.h index bfda7dbe250..adf64a80c85 100644 --- a/libs/utils/src/EntityManagerImpl.h +++ b/libs/utils/src/EntityManagerImpl.h @@ -48,6 +48,16 @@ class UTILS_PRIVATE EntityManagerImpl : public EntityManager { using EntityManager::create; using EntityManager::destroy; + UTILS_NOINLINE + size_t getEntityCount() const noexcept { + std::lock_guard const lock(mFreeListLock); + if (mCurrentIndex < RAW_INDEX_COUNT) { + return (mCurrentIndex - 1) - mFreeList.size(); + } else { + return getMaxEntityCount() - mFreeList.size(); + } + } + UTILS_NOINLINE void create(size_t n, Entity* entities) { Entity::Type index{}; diff --git a/libs/utils/src/NameComponentManager.cpp b/libs/utils/src/NameComponentManager.cpp index 98bb3839a32..eae5df4a163 100644 --- a/libs/utils/src/NameComponentManager.cpp +++ b/libs/utils/src/NameComponentManager.cpp @@ -21,7 +21,7 @@ namespace utils { static constexpr size_t NAME = 0; -NameComponentManager::NameComponentManager(EntityManager& em) { +NameComponentManager::NameComponentManager(EntityManager&) { } NameComponentManager::~NameComponentManager() = default; @@ -36,14 +36,6 @@ const char* NameComponentManager::getName(Instance instance) const noexcept { return elementAt(instance).c_str(); } -size_t NameComponentManager::getComponentCount() const noexcept { - return SingleInstanceComponentManager::getComponentCount(); -} - -Entity const* NameComponentManager::getEntities() const noexcept { - return SingleInstanceComponentManager::getEntities(); -} - void NameComponentManager::addComponent(Entity e) { SingleInstanceComponentManager::addComponent(e); } @@ -52,8 +44,4 @@ void NameComponentManager::removeComponent(Entity e) { SingleInstanceComponentManager::removeComponent(e); } -void NameComponentManager::gc(const EntityManager& em, size_t ratio) noexcept { - SingleInstanceComponentManager::gc(em, ratio); -} - } // namespace utils diff --git a/libs/viewer/src/Settings.cpp b/libs/viewer/src/Settings.cpp index 22b64588b09..febeb321fd5 100644 --- a/libs/viewer/src/Settings.cpp +++ b/libs/viewer/src/Settings.cpp @@ -612,8 +612,10 @@ void applySettings(Engine* engine, const LightSettings& settings, IndirectLight* } for (size_t i = 0; i < sceneLightCount; i++) { auto const li = lm->getInstance(sceneLights[i]); - lm->setShadowCaster(li, settings.enableShadows); - lm->setShadowOptions(li, settings.shadowOptions); + if (li) { + lm->setShadowCaster(li, settings.enableShadows); + lm->setShadowOptions(li, settings.shadowOptions); + } } view->setSoftShadowOptions(settings.softShadowOptions); } diff --git a/libs/viewer/src/ViewerGui.cpp b/libs/viewer/src/ViewerGui.cpp index 8e0177538dc..37d6420491c 100644 --- a/libs/viewer/src/ViewerGui.cpp +++ b/libs/viewer/src/ViewerGui.cpp @@ -1045,7 +1045,7 @@ void ViewerGui::updateUserInterface() { std::vector names; names.reserve(cameraCount + 1); - names.push_back("Free camera"); + names.emplace_back("Free camera"); int c = 0; for (size_t i = 0; i < cameraCount; i++) { const char* n = mAsset->getName(cameras[i]); @@ -1060,8 +1060,8 @@ void ViewerGui::updateUserInterface() { std::vector cstrings; cstrings.reserve(names.size()); - for (size_t i = 0; i < names.size(); i++) { - cstrings.push_back(names[i].c_str()); + for (const auto & name : names) { + cstrings.push_back(name.c_str()); } ImGui::ListBox("Cameras", &mCurrentCamera, cstrings.data(), cstrings.size()); @@ -1083,8 +1083,16 @@ void ViewerGui::updateUserInterface() { // At this point, all View settings have been modified, // so we can now push them into the Filament View. applySettings(mEngine, mSettings.view, mView); + + auto lights = utils::FixedCapacityVector::with_capacity(mScene->getEntityCount()); + mScene->forEach([&](utils::Entity entity) { + if (lm.hasComponent(entity)) { + lights.push_back(entity); + } + }); + applySettings(mEngine, mSettings.lighting, mIndirectLight, mSunlight, - lm.getEntities(), lm.getComponentCount(), &lm, mScene, mView); + lights.data(), lights.size(), &lm, mScene, mView); // TODO(prideout): add support for hierarchy, animation and variant selection in remote mode. To // support these features, we will need to send a message (list of strings) from DebugServer to diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp index 7e31c167866..90e4171b7a5 100644 --- a/web/filament-js/jsbindings.cpp +++ b/web/filament-js/jsbindings.cpp @@ -688,6 +688,7 @@ class_("Scene") .function("getSkybox", &Scene::getSkybox, allow_raw_pointers()) .function("setIndirectLight", &Scene::setIndirectLight, allow_raw_pointers()) .function("getIndirectLight", &Scene::getIndirectLight, allow_raw_pointers()) + .function("getEntityCount", &Scene::getEntityCount) .function("getRenderableCount", &Scene::getRenderableCount) .function("getLightCount", &Scene::getLightCount);