diff --git a/android/gltfio-android/CMakeLists.txt b/android/gltfio-android/CMakeLists.txt
index 12949c7a03..765581a25d 100644
--- a/android/gltfio-android/CMakeLists.txt
+++ b/android/gltfio-android/CMakeLists.txt
@@ -40,30 +40,33 @@ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,
set(GLTFIO_SRCS
${GLTFIO_DIR}/include/gltfio/Animator.h
${GLTFIO_DIR}/include/gltfio/AssetLoader.h
- ${GLTFIO_DIR}/include/gltfio/MaterialProvider.h
- ${GLTFIO_DIR}/include/gltfio/ResourceLoader.h
${GLTFIO_DIR}/include/gltfio/FilamentAsset.h
${GLTFIO_DIR}/include/gltfio/FilamentInstance.h
+ ${GLTFIO_DIR}/include/gltfio/MaterialProvider.h
+ ${GLTFIO_DIR}/include/gltfio/NodeManager.h
+ ${GLTFIO_DIR}/include/gltfio/ResourceLoader.h
${GLTFIO_DIR}/include/gltfio/TextureProvider.h
${GLTFIO_DIR}/include/gltfio/math.h
${GLTFIO_DIR}/src/Animator.cpp
${GLTFIO_DIR}/src/AssetLoader.cpp
- ${GLTFIO_DIR}/src/DracoCache.cpp
- ${GLTFIO_DIR}/src/DracoCache.h
${GLTFIO_DIR}/src/DependencyGraph.cpp
${GLTFIO_DIR}/src/DependencyGraph.h
+ ${GLTFIO_DIR}/src/DracoCache.cpp
+ ${GLTFIO_DIR}/src/DracoCache.h
${GLTFIO_DIR}/src/FFilamentAsset.h
- ${GLTFIO_DIR}/src/FilamentAsset.cpp
${GLTFIO_DIR}/src/FFilamentInstance.h
+ ${GLTFIO_DIR}/src/FilamentAsset.cpp
${GLTFIO_DIR}/src/FilamentInstance.cpp
+ ${GLTFIO_DIR}/src/FNodeManager.h
${GLTFIO_DIR}/src/GltfEnums.h
${GLTFIO_DIR}/src/Ktx2Provider.cpp
${GLTFIO_DIR}/src/MaterialProvider.cpp
+ ${GLTFIO_DIR}/src/NodeManager.cpp
${GLTFIO_DIR}/src/ResourceLoader.cpp
${GLTFIO_DIR}/src/StbProvider.cpp
- ${GLTFIO_DIR}/src/TangentsJob.h
${GLTFIO_DIR}/src/TangentsJob.cpp
+ ${GLTFIO_DIR}/src/TangentsJob.h
${GLTFIO_DIR}/src/UbershaderLoader.cpp
${GLTFIO_DIR}/src/Wireframe.cpp
${GLTFIO_DIR}/src/Wireframe.h
diff --git a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java
index 747db67333..ed7af8e0dc 100644
--- a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java
+++ b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java
@@ -30,9 +30,9 @@ import com.google.android.filament.MaterialInstance;
*
*
For usage instructions, see the documentation for {@link AssetLoader}.
*
- * This class owns a hierarchy of entities that have been loaded from a glTF asset. Every entity has
- * a TransformManager component, and some entities also have
- * NameComponentManager and/or RenderableManager components.
+ * This class owns a hierarchy of entities that have been loaded from a glTF asset. Every entity
+ * has a TransformManager component, and some entities also have compnents managed by
+ * NameComponentManager, RenderableManager, and others.
*
* In addition to the aforementioned entities, an asset has strong ownership over a list of
* VertexBuffer, IndexBuffer, MaterialInstance, and
diff --git a/libs/gltfio/CMakeLists.txt b/libs/gltfio/CMakeLists.txt
index ee0347b916..c55f2d648b 100644
--- a/libs/gltfio/CMakeLists.txt
+++ b/libs/gltfio/CMakeLists.txt
@@ -10,10 +10,11 @@ set(PUBLIC_HDR_DIR include)
set(PUBLIC_HDRS
include/gltfio/Animator.h
include/gltfio/AssetLoader.h
- include/gltfio/MaterialProvider.h
- include/gltfio/ResourceLoader.h
include/gltfio/FilamentAsset.h
include/gltfio/FilamentInstance.h
+ include/gltfio/MaterialProvider.h
+ include/gltfio/NodeManager.h
+ include/gltfio/ResourceLoader.h
include/gltfio/TextureProvider.h
include/gltfio/math.h
)
@@ -23,19 +24,21 @@ set(SRCS
src/AssetLoader.cpp
src/DependencyGraph.cpp
src/DependencyGraph.h
- src/DracoCache.h
src/DracoCache.cpp
+ src/DracoCache.h
src/FFilamentAsset.h
- src/FilamentAsset.cpp
src/FFilamentInstance.h
+ src/FilamentAsset.cpp
src/FilamentInstance.cpp
+ src/FNodeManager.h
src/GltfEnums.h
src/Ktx2Provider.cpp
src/MaterialProvider.cpp
+ src/NodeManager.cpp
src/ResourceLoader.cpp
src/StbProvider.cpp
- src/TangentsJob.h
src/TangentsJob.cpp
+ src/TangentsJob.h
src/UbershaderLoader.cpp
src/Wireframe.cpp
src/Wireframe.h
diff --git a/libs/gltfio/include/gltfio/AssetLoader.h b/libs/gltfio/include/gltfio/AssetLoader.h
index 90491c9852..91dc557faf 100644
--- a/libs/gltfio/include/gltfio/AssetLoader.h
+++ b/libs/gltfio/include/gltfio/AssetLoader.h
@@ -36,6 +36,8 @@ namespace utils {
*/
namespace gltfio {
+class NodeManager;
+
/**
* \struct AssetConfiguration AssetLoader.h gltfio/AssetLoader.h
* \brief Construction parameters for AssetLoader.
@@ -70,7 +72,8 @@ struct AssetConfiguration {
* object, which is a bundle of Filament entities, material instances, textures, vertex buffers,
* and index buffers.
*
- * Clients must use AssetLoader to create and destroy FilamentAsset objects.
+ * Clients must use AssetLoader to create and destroy FilamentAsset objects. This is similar to
+ * how filament::Engine is used to create and destroy core objects like VertexBuffer.
*
* AssetLoader does not fetch external buffer data or create textures on its own. Clients can use
* ResourceLoader for this, which obtains the URI list from the asset. This is demonstrated in the
@@ -226,7 +229,9 @@ public:
utils::NameComponentManager* getNames() const noexcept;
- MaterialProvider* getMaterialProvider() const noexcept;
+ NodeManager& getNodeManager() noexcept;
+
+ MaterialProvider& getMaterialProvider() noexcept;
/*! \cond PRIVATE */
protected:
diff --git a/libs/gltfio/include/gltfio/FilamentAsset.h b/libs/gltfio/include/gltfio/FilamentAsset.h
index b6f4c2ae7c..c3dd8da477 100644
--- a/libs/gltfio/include/gltfio/FilamentAsset.h
+++ b/libs/gltfio/include/gltfio/FilamentAsset.h
@@ -42,7 +42,7 @@ class FilamentInstance;
*
* This class owns a hierarchy of entities that have been loaded from a glTF asset. Every entity has
* a filament::TransformManager component, and some entities also have \c Name, \c Renderable,
- * \c Light, or \c Camera components.
+ * \c Light, \c Camera, or \c Node components.
*
* In addition to the aforementioned entities, an asset has strong ownership over a list of
* filament::VertexBuffer, filament::IndexBuffer, filament::MaterialInstance, filament::Texture,
diff --git a/libs/gltfio/include/gltfio/NodeManager.h b/libs/gltfio/include/gltfio/NodeManager.h
new file mode 100644
index 0000000000..7d97083511
--- /dev/null
+++ b/libs/gltfio/include/gltfio/NodeManager.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef GLTFIO_NODEMANAGER_H
+#define GLTFIO_NODEMANAGER_H
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace utils {
+class Entity;
+} // namespace utils
+
+namespace gltfio {
+
+class FNodeManager;
+
+/**
+ * NodeManager is used to add annotate entities with glTF-specific information.
+ *
+ * Node components are created by gltfio and exposed to users to allow inspection.
+ *
+ * Nodes do not store the glTF hierarchy or names; see TransformManager and NameComponentManager.
+ */
+class UTILS_PUBLIC NodeManager {
+public:
+ using Instance = utils::EntityInstance;
+ using Entity = utils::Entity;
+ using CString = utils::CString;
+
+ /**
+ * Returns whether a particular Entity is associated with a component of this NodeManager
+ * @param e An Entity.
+ * @return true if this Entity has a component associated with this manager.
+ */
+ bool hasComponent(Entity e) const noexcept;
+
+ /**
+ * Gets an Instance representing the node component associated with the given Entity.
+ * @param e An Entity.
+ * @return An Instance object, which represents the node component associated with the Entity e.
+ * @note Use Instance::isValid() to make sure the component exists.
+ * @see hasComponent()
+ */
+ Instance getInstance(Entity e) const noexcept;
+
+ /**
+ * Creates a node component and associates it with the given entity.
+ * @param entity An Entity to associate a node component with.
+ *
+ * If this component already exists on the given entity, it is first destroyed as if
+ * destroy(Entity e) was called.
+ *
+ * @see destroy()
+ */
+ void create(Entity entity);
+
+ /**
+ * Destroys this component from the given entity.
+ * @param e An entity.
+ *
+ * @see create()
+ */
+ void destroy(Entity e) noexcept;
+
+ void setMorphTargetNames(Instance ci, utils::FixedCapacityVector names) noexcept;
+ const utils::FixedCapacityVector& getMorphTargetNames(Instance ci) const noexcept;
+
+ void setExtras(Instance ci, CString extras) noexcept;
+ const CString& getExtras(Instance ci) const noexcept;
+
+ void setSceneMembership(Instance ci, utils::bitset32 scenes) noexcept;
+ utils::bitset32 getSceneMembership(Instance ci) const noexcept;
+
+protected:
+ NodeManager() noexcept = default;
+ ~NodeManager() = default;
+
+public:
+ NodeManager(NodeManager const&) = delete;
+ NodeManager(NodeManager&&) = delete;
+ NodeManager& operator=(NodeManager const&) = delete;
+ NodeManager& operator=(NodeManager&&) = delete;
+};
+
+} // namespace gltfio
+
+
+#endif // GLTFIO_NODEMANAGER_H
diff --git a/libs/gltfio/src/AssetLoader.cpp b/libs/gltfio/src/AssetLoader.cpp
index 6ac421428b..2bc8447b6c 100644
--- a/libs/gltfio/src/AssetLoader.cpp
+++ b/libs/gltfio/src/AssetLoader.cpp
@@ -20,6 +20,7 @@
#include
#include "FFilamentAsset.h"
+#include "FNodeManager.h"
#include "GltfEnums.h"
#include
@@ -93,8 +94,8 @@ struct FAssetLoader : public AssetLoader {
mRenderableManager(config.engine->getRenderableManager()),
mNameManager(config.names),
mTransformManager(config.engine->getTransformManager()),
- mMaterials(config.materials),
- mEngine(config.engine),
+ mMaterials(*config.materials),
+ mEngine(*config.engine),
mDefaultNodeName(config.defaultNodeName) {}
FFilamentAsset* createAssetFromJson(const uint8_t* bytes, uint32_t nbytes);
@@ -113,15 +114,19 @@ struct FAssetLoader : public AssetLoader {
}
size_t getMaterialsCount() const noexcept {
- return mMaterials->getMaterialsCount();
+ return mMaterials.getMaterialsCount();
}
NameComponentManager* getNames() const noexcept {
return mNameManager;
}
+ NodeManager& getNodeManager() noexcept {
+ return mNodeManager;
+ }
+
const Material* const* getMaterials() const noexcept {
- return mMaterials->getMaterials();
+ return mMaterials.getMaterials();
}
void createAsset(const cgltf_data* srcAsset, size_t numInstances);
@@ -147,10 +152,11 @@ struct FAssetLoader : public AssetLoader {
EntityManager& mEntityManager;
RenderableManager& mRenderableManager;
- NameComponentManager* mNameManager;
+ NameComponentManager* const mNameManager;
TransformManager& mTransformManager;
- MaterialProvider* mMaterials;
- Engine* mEngine;
+ MaterialProvider& mMaterials;
+ Engine& mEngine;
+ FNodeManager mNodeManager;
// Transient state used only for the asset currently being loaded:
FFilamentAsset* mResult;
@@ -270,7 +276,7 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
}
#endif
- mResult = new FFilamentAsset(mEngine, mNameManager, &mEntityManager, srcAsset);
+ mResult = new FFilamentAsset(&mEngine, mNameManager, &mEntityManager, &mNodeManager, srcAsset);
mDummyBufferObject = nullptr;
// If there is no default scene specified, then the default is the first one.
@@ -321,7 +327,7 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
// Sort the entities so that the renderable ones come first. This allows us to expose
// a "renderables only" pointer without storing a separate list.
- const auto& rm = mEngine->getRenderableManager();
+ const auto& rm = mEngine.getRenderableManager();
std::partition(mResult->mEntities.begin(), mResult->mEntities.end(), [&rm](Entity a) {
return rm.hasComponent(a);
});
@@ -383,6 +389,7 @@ FFilamentInstance* FAssetLoader::createInstance(FFilamentAsset* primary,
void FAssetLoader::createEntity(const cgltf_data* srcAsset, const cgltf_node* node, Entity parent,
bool enableLight, FFilamentInstance* instance) {
Entity entity = mEntityManager.create();
+ mNodeManager.create(entity);
// Always create a transform component to reflect the original hierarchy.
mat4f localTransform;
@@ -402,8 +409,8 @@ void FAssetLoader::createEntity(const cgltf_data* srcAsset, const cgltf_node* no
const cgltf_size extras_size = node->extras.end_offset - node->extras.start_offset;
if (extras_size > 0) {
const cgltf_data* srcAsset = mResult->mSourceAsset->hierarchy;
- mResult->mNodeExtras[entity] = CString(
- srcAsset->json + node->extras.start_offset, extras_size);
+ mNodeManager.setExtras(mNodeManager.getInstance(entity),
+ {srcAsset->json + node->extras.start_offset, extras_size});
}
// Update the asset's entity list and private node mapping.
@@ -525,12 +532,12 @@ void FAssetLoader::createRenderable(const cgltf_data* srcAsset, const cgltf_node
}
}
- auto& morphTargetNames = mResult->mMorphTargetNames[entity];
- assert_invariant(morphTargetNames.empty());
- morphTargetNames = FixedCapacityVector(numMorphTargets);
+ FixedCapacityVector morphTargetNames(numMorphTargets);
for (cgltf_size i = 0, c = mesh->target_names_count; i < c; ++i) {
- morphTargetNames[i] = StaticString::make(mesh->target_names[i]);
+ morphTargetNames[i] = CString(mesh->target_names[i]);
}
+ mNodeManager.setMorphTargetNames(mNodeManager.getInstance(entity),
+ std::move(morphTargetNames));
const Aabb transformed = aabb.transform(worldTransform);
@@ -556,7 +563,7 @@ void FAssetLoader::createRenderable(const cgltf_data* srcAsset, const cgltf_node
.culling(true)
.castShadows(true)
.receiveShadows(true)
- .build(*mEngine, entity);
+ .build(mEngine, entity);
// According to the spec, the mesh may or may not specify default weights, regardless of whether
// it actually has morph targets. If it has morphing enabled then the default weights are 0. If
@@ -630,7 +637,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
indices = IndexBuffer::Builder()
.indexCount(accessor->count)
.bufferType(indexType)
- .build(*mEngine);
+ .build(mEngine);
BufferSlot slot = { accessor };
slot.indexBuffer = indices;
@@ -642,7 +649,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
indices = IndexBuffer::Builder()
.indexCount(vertexCount)
.bufferType(IndexBuffer::IndexType::UINT)
- .build(*mEngine);
+ .build(mEngine);
const size_t indexDataSize = vertexCount * sizeof(uint32_t);
uint32_t* indexData = (uint32_t*) malloc(indexDataSize);
@@ -650,7 +657,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
indexData[i] = i;
}
IndexBuffer::BufferDescriptor bd(indexData, indexDataSize, FREE_CALLBACK);
- indices->setBuffer(*mEngine, std::move(bd));
+ indices->setBuffer(mEngine, std::move(bd));
}
mResult->mIndexBuffers.push_back(indices);
@@ -822,21 +829,21 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
// the sizes match.
bool needsDummyData = false;
- if (mMaterials->needsDummyData(VertexAttribute::UV0) && !hasUv0) {
+ if (mMaterials.needsDummyData(VertexAttribute::UV0) && !hasUv0) {
needsDummyData = true;
hasUv0 = true;
vbb.attribute(VertexAttribute::UV0, slot, VertexBuffer::AttributeType::USHORT2);
vbb.normalized(VertexAttribute::UV0);
}
- if (mMaterials->needsDummyData(VertexAttribute::UV1) && !hasUv1) {
+ if (mMaterials.needsDummyData(VertexAttribute::UV1) && !hasUv1) {
hasUv1 = true;
needsDummyData = true;
vbb.attribute(VertexAttribute::UV1, slot, VertexBuffer::AttributeType::USHORT2);
vbb.normalized(VertexAttribute::UV1);
}
- if (mMaterials->needsDummyData(VertexAttribute::COLOR) && !hasVertexColor) {
+ if (mMaterials.needsDummyData(VertexAttribute::COLOR) && !hasVertexColor) {
needsDummyData = true;
vbb.attribute(VertexAttribute::COLOR, slot, VertexBuffer::AttributeType::UBYTE4);
vbb.normalized(VertexAttribute::COLOR);
@@ -859,7 +866,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
vbb.bufferCount(needsDummyData ? slot + 1 : slot);
- VertexBuffer* vertices = vbb.build(*mEngine);
+ VertexBuffer* vertices = vbb.build(mEngine);
outPrim->indices = indices;
outPrim->vertices = vertices;
@@ -874,7 +881,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
MorphTargetBuffer* targets = MorphTargetBuffer::Builder()
.vertexCount(vertexCount)
.count(targetsCount)
- .build(*mEngine);
+ .build(mEngine);
outPrim->targets = targets;
mResult->mMorphTargetBuffers.push_back(targets);
const cgltf_accessor* previous = nullptr;
@@ -902,14 +909,14 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
if (needsDummyData) {
const uint32_t requiredSize = sizeof(ubyte4) * vertexCount;
if (mDummyBufferObject == nullptr || requiredSize > mDummyBufferObject->getByteCount()) {
- mDummyBufferObject = BufferObject::Builder().size(requiredSize).build(*mEngine);
+ mDummyBufferObject = BufferObject::Builder().size(requiredSize).build(mEngine);
mResult->mBufferObjects.push_back(mDummyBufferObject);
uint32_t* dummyData = (uint32_t*) malloc(requiredSize);
memset(dummyData, 0xff, requiredSize);
VertexBuffer::BufferDescriptor bd(dummyData, requiredSize, FREE_CALLBACK);
- mDummyBufferObject->setBuffer(*mEngine, std::move(bd));
+ mDummyBufferObject->setBuffer(mEngine, std::move(bd));
}
- vertices->setBufferObjectAt(*mEngine, slot, mDummyBufferObject);
+ vertices->setBufferObjectAt(mEngine, slot, mDummyBufferObject);
}
return true;
@@ -947,12 +954,12 @@ void FAssetLoader::createLight(const cgltf_light* light, Entity entity) {
builder.falloff(light->range);
}
- builder.build(*mEngine, entity);
+ builder.build(mEngine, entity);
mResult->mLightEntities.push_back(entity);
}
void FAssetLoader::createCamera(const cgltf_camera* camera, Entity entity) {
- Camera* filamentCamera = mEngine->createCamera(entity);
+ Camera* filamentCamera = mEngine.createCamera(entity);
if (camera->type == cgltf_camera_type_perspective) {
auto& projection = camera->data.perspective;
@@ -1115,7 +1122,7 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsse
// This not only creates a material instance, it modifies the material key according to our
// rendering constraints. For example, Filament only supports 2 sets of texture coordinates.
- MaterialInstance* mi = mMaterials->createMaterialInstance(&matkey, uvmap, inputMat->name,
+ MaterialInstance* mi = mMaterials.createMaterialInstance(&matkey, uvmap, inputMat->name,
extras.c_str());
if (!mi) {
slog.e << "No material with the specified requirements exists." << io::endl;
@@ -1420,7 +1427,7 @@ const Material* const* AssetLoader::getMaterials() const noexcept {
return upcast(this)->getMaterials();
}
-MaterialProvider* AssetLoader::getMaterialProvider() const noexcept {
+MaterialProvider& AssetLoader::getMaterialProvider() noexcept {
return upcast(this)->mMaterials;
}
diff --git a/libs/gltfio/src/FFilamentAsset.h b/libs/gltfio/src/FFilamentAsset.h
index 0c78e5688a..986971a716 100644
--- a/libs/gltfio/src/FFilamentAsset.h
+++ b/libs/gltfio/src/FFilamentAsset.h
@@ -18,6 +18,7 @@
#define GLTFIO_FFILAMENTASSET_H
#include
+#include
#include
#include
@@ -116,8 +117,10 @@ using MatInstanceCache = tsl::robin_map;
struct FFilamentAsset : public FilamentAsset {
FFilamentAsset(filament::Engine* engine, utils::NameComponentManager* names,
- utils::EntityManager* entityManager, const cgltf_data* srcAsset) :
- mEngine(engine), mNameManager(names), mEntityManager(entityManager) {
+ utils::EntityManager* entityManager, NodeManager* nodeManager,
+ const cgltf_data* srcAsset) :
+ mEngine(engine), mNameManager(names), mEntityManager(entityManager),
+ mNodeManager(nodeManager) {
mSourceAsset.reset(new SourceAsset {(cgltf_data*)srcAsset});
}
@@ -255,9 +258,10 @@ struct FFilamentAsset : public FilamentAsset {
void createAnimators();
- filament::Engine* mEngine;
- utils::NameComponentManager* mNameManager;
- utils::EntityManager* mEntityManager;
+ filament::Engine* const mEngine;
+ utils::NameComponentManager* const mNameManager;
+ utils::EntityManager* const mEntityManager;
+ NodeManager* const mNodeManager;
std::vector mEntities; // sorted such that renderables come first
std::vector mLightEntities;
std::vector mCameraEntities;
@@ -278,8 +282,6 @@ struct FFilamentAsset : public FilamentAsset {
bool mResourcesLoaded = false;
DependencyGraph mDependencyGraph;
tsl::htrie_map> mNameToEntity;
- tsl::robin_map mNodeExtras;
- tsl::robin_map> mMorphTargetNames;
utils::CString mAssetExtras;
// Sentinels for situations where ResourceLoader needs to generate data.
diff --git a/libs/gltfio/src/FNodeManager.h b/libs/gltfio/src/FNodeManager.h
new file mode 100644
index 0000000000..98a402e3ac
--- /dev/null
+++ b/libs/gltfio/src/FNodeManager.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef GLTFIO_FNODEMANAGER_H
+#define GLTFIO_FNODEMANAGER_H
+
+#include "upcast.h"
+
+#include
+
+#include
+#include
+#include
+#include
+
+namespace gltfio {
+
+class UTILS_PRIVATE FNodeManager : public NodeManager {
+public:
+ using Instance = NodeManager::Instance;
+
+ FNodeManager() noexcept {}
+
+ ~FNodeManager() noexcept {
+ assert_invariant(mManager.getComponentCount() == 0);
+ }
+
+ void terminate() noexcept;
+
+ bool hasComponent(utils::Entity e) const noexcept {
+ return mManager.hasComponent(e);
+ }
+
+ Instance getInstance(utils::Entity e) const noexcept {
+ return Instance(mManager.getInstance(e));
+ }
+
+ void create(utils::Entity entity) {
+ if (UTILS_UNLIKELY(mManager.hasComponent(entity))) {
+ destroy(entity);
+ }
+ Instance ci = mManager.addComponent(entity);
+ assert_invariant(ci);
+ }
+
+ void destroy(utils::Entity e) noexcept {
+ if (Instance ci = mManager.getInstance(e); ci) {
+ mManager.removeComponent(e);
+ }
+ }
+
+ void gc(utils::EntityManager& em) noexcept {
+ mManager.gc(em);
+ }
+
+ void setMorphTargetNames(Instance ci, utils::FixedCapacityVector names) noexcept {
+ assert_invariant(ci.isValid());
+ mManager[ci].morphTargetNames = std::move(names);
+ }
+
+ const utils::FixedCapacityVector& getMorphTargetNames(Instance ci) const noexcept {
+ return mManager[ci].morphTargetNames;
+ }
+
+ void setExtras(Instance ci, CString extras) noexcept {
+ mManager[ci].extras = std::move(extras);
+ }
+
+ const CString& getExtras(Instance ci) const noexcept {
+ return mManager[ci].extras;
+ }
+
+ void setSceneMembership(Instance ci, utils::bitset32 scenes) noexcept {
+ mManager[ci].scenes = scenes;
+ }
+
+ utils::bitset32 getSceneMembership(Instance ci) const noexcept {
+ return mManager[ci].scenes;
+ }
+
+private:
+ enum {
+ MORPH_TARGET_NAMES,
+ EXTRAS_STRING,
+ SCENE_MEMBERSHIP,
+ };
+
+ using Base = utils::SingleInstanceComponentManager< // 24 bytes
+ utils::FixedCapacityVector, // 16
+ CString, // 8
+ utils::bitset32>; // 4
+
+ struct Sim : public Base {
+ using Base::gc;
+ using Base::swap;
+
+ typename Base::SoA& getSoA() { return mData; }
+
+ struct Proxy {
+ UTILS_ALWAYS_INLINE
+ Proxy(Base& sim, utils::EntityInstanceBase::Type i) noexcept :
+ morphTargetNames{ sim, i } { }
+
+ union {
+ Field morphTargetNames;
+ Field extras;
+ Field scenes;
+ };
+ };
+
+ UTILS_ALWAYS_INLINE Proxy operator[](Instance i) noexcept {
+ return { *this, i };
+ }
+ UTILS_ALWAYS_INLINE const Proxy operator[](Instance i) const noexcept {
+ return { const_cast(*this), i };
+ }
+ };
+
+ Sim mManager;
+};
+
+FILAMENT_UPCAST(NodeManager)
+
+} // namespace gltfio
+
+#endif // GLTFIO_FNODEMANAGER_H
diff --git a/libs/gltfio/src/FilamentAsset.cpp b/libs/gltfio/src/FilamentAsset.cpp
index 4c97aa77c1..e2bbb9dedf 100644
--- a/libs/gltfio/src/FilamentAsset.cpp
+++ b/libs/gltfio/src/FilamentAsset.cpp
@@ -54,6 +54,8 @@ FFilamentAsset::~FFilamentAsset() {
if (mNameManager) {
mNameManager->removeComponent(entity);
}
+ // Destroy the node component.
+ mNodeManager->destroy(entity);
// Destroy the actual entity.
mEntityManager->destroy(entity);
}
@@ -81,8 +83,7 @@ const char* FFilamentAsset::getExtras(utils::Entity entity) const noexcept {
if (entity.isNull()) {
return mAssetExtras.c_str();
}
- const auto iter = mNodeExtras.find(entity);
- return iter == mNodeExtras.cend() ? nullptr : iter->second.c_str();
+ return mNodeManager->getExtras(mNodeManager->getInstance(entity)).c_str();
}
void FFilamentAsset::createAnimators() {
@@ -124,17 +125,12 @@ const char* FFilamentAsset::getMorphTargetNameAt(utils::Entity entity,
return nullptr;
}
- const auto iter = mMorphTargetNames.find(entity);
- if (iter == mMorphTargetNames.end()) {
+ const auto& names = mNodeManager->getMorphTargetNames(mNodeManager->getInstance(entity));
+ if (targetIndex >= names.size()) {
return nullptr;
}
- const auto& morphTargetNames = iter->second;
- if (targetIndex >= morphTargetNames.size()) {
- return nullptr;
- }
-
- return morphTargetNames[targetIndex].c_str();
+ return names[targetIndex].c_str();
}
size_t FFilamentAsset::getMorphTargetCountAt(utils::Entity entity) const noexcept {
@@ -142,12 +138,8 @@ size_t FFilamentAsset::getMorphTargetCountAt(utils::Entity entity) const noexcep
return 0;
}
- const auto iter = mMorphTargetNames.find(entity);
- if (iter == mMorphTargetNames.end()) {
- return 0;
- }
-
- return iter->second.size();
+ const auto& names = mNodeManager->getMorphTargetNames(mNodeManager->getInstance(entity));
+ return names.size();
}
size_t FFilamentAsset::getMaterialVariantCount() const noexcept {
diff --git a/libs/gltfio/src/NodeManager.cpp b/libs/gltfio/src/NodeManager.cpp
new file mode 100644
index 0000000000..d6a337479e
--- /dev/null
+++ b/libs/gltfio/src/NodeManager.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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 "FNodeManager.h"
+
+#include
+
+#include "upcast.h"
+
+using namespace utils;
+
+namespace gltfio {
+
+using Instance = NodeManager::Instance;
+
+void FNodeManager::terminate() noexcept {
+ auto& manager = mManager;
+ if (!manager.empty()) {
+#ifndef NDEBUG
+ utils::slog.d << "cleaning up " << manager.getComponentCount()
+ << " leaked node components" << utils::io::endl;
+#endif
+ while (!manager.empty()) {
+ Instance ci = manager.end() - 1;
+ manager.removeComponent(manager.getEntity(ci));
+ }
+ }
+}
+
+bool NodeManager::hasComponent(Entity e) const noexcept {
+ return upcast(this)->hasComponent(e);
+}
+
+Instance NodeManager::getInstance(Entity e) const noexcept {
+ return upcast(this)->getInstance(e);
+}
+
+void NodeManager::create(Entity entity) {
+ upcast(this)->create(entity);
+}
+
+void NodeManager::destroy(Entity e) noexcept {
+ upcast(this)->destroy(e);
+}
+
+void NodeManager::setMorphTargetNames(Instance ci, FixedCapacityVector names) noexcept {
+ upcast(this)->setMorphTargetNames(ci, std::move(names));
+}
+
+const FixedCapacityVector& NodeManager::getMorphTargetNames(Instance ci) const noexcept {
+ return upcast(this)->getMorphTargetNames(ci);
+}
+
+void NodeManager::setExtras(Instance ci, CString extras) noexcept {
+ return upcast(this)->setExtras(ci, std::move(extras));
+}
+
+const CString& NodeManager::getExtras(Instance ci) const noexcept {
+ return upcast(this)->getExtras(ci);
+}
+
+void NodeManager::setSceneMembership(Instance ci, bitset32 scenes) noexcept {
+ upcast(this)->setSceneMembership(ci, scenes);
+}
+
+bitset32 NodeManager::getSceneMembership(Instance ci) const noexcept {
+ return upcast(this)->getSceneMembership(ci);
+}
+
+} // namespace gltfio