Introduce gltfio::NodeManager, remove some robin_map. (#5522)

* Introduce gltfio::NodeManager, remove some robin_map.

* Incorporate code review feedback.
This commit is contained in:
Philip Rideout
2022-05-06 16:14:56 -07:00
committed by GitHub
parent 626beee345
commit a68a478bf3
11 changed files with 412 additions and 71 deletions
+9 -6
View File
@@ -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
@@ -30,9 +30,9 @@ import com.google.android.filament.MaterialInstance;
*
* <p>For usage instructions, see the documentation for {@link AssetLoader}.</p>
*
* <p>This class owns a hierarchy of entities that have been loaded from a glTF asset. Every entity has
* a <code>TransformManager</code> component, and some entities also have
* <code>NameComponentManager</code> and/or <code>RenderableManager</code> components.</p>
* <p>This class owns a hierarchy of entities that have been loaded from a glTF asset. Every entity
* has a <code>TransformManager</code> component, and some entities also have compnents managed by
* <code>NameComponentManager</code>, <code>RenderableManager</code>, and others.</p>
*
* <p>In addition to the aforementioned entities, an asset has strong ownership over a list of
* <code>VertexBuffer</code>, <code>IndexBuffer</code>, <code>MaterialInstance</code>, and
+8 -5
View File
@@ -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
+7 -2
View File
@@ -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:
+1 -1
View File
@@ -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,
+107
View File
@@ -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 <filament/FilamentAPI.h>
#include <utils/bitset.h>
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/EntityInstance.h>
#include <utils/FixedCapacityVector.h>
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<NodeManager>;
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<CString> names) noexcept;
const utils::FixedCapacityVector<CString>& 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
+38 -31
View File
@@ -20,6 +20,7 @@
#include <gltfio/math.h>
#include "FFilamentAsset.h"
#include "FNodeManager.h"
#include "GltfEnums.h"
#include <filament/Box.h>
@@ -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<CString>(numMorphTargets);
FixedCapacityVector<CString> 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;
}
+9 -7
View File
@@ -18,6 +18,7 @@
#define GLTFIO_FFILAMENTASSET_H
#include <gltfio/FilamentAsset.h>
#include <gltfio/NodeManager.h>
#include <filament/Engine.h>
#include <filament/IndexBuffer.h>
@@ -116,8 +117,10 @@ using MatInstanceCache = tsl::robin_map<intptr_t, MaterialEntry>;
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<utils::Entity> mEntities; // sorted such that renderables come first
std::vector<utils::Entity> mLightEntities;
std::vector<utils::Entity> mCameraEntities;
@@ -278,8 +282,6 @@ struct FFilamentAsset : public FilamentAsset {
bool mResourcesLoaded = false;
DependencyGraph mDependencyGraph;
tsl::htrie_map<char, std::vector<utils::Entity>> mNameToEntity;
tsl::robin_map<utils::Entity, utils::CString> mNodeExtras;
tsl::robin_map<utils::Entity, utils::FixedCapacityVector<utils::CString>> mMorphTargetNames;
utils::CString mAssetExtras;
// Sentinels for situations where ResourceLoader needs to generate data.
+139
View File
@@ -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 <gltfio/NodeManager.h>
#include <utils/compiler.h>
#include <utils/SingleInstanceComponentManager.h>
#include <utils/Entity.h>
#include <utils/Slice.h>
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<CString> names) noexcept {
assert_invariant(ci.isValid());
mManager[ci].morphTargetNames = std::move(names);
}
const utils::FixedCapacityVector<CString>& 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<CString>, // 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<MORPH_TARGET_NAMES> morphTargetNames;
Field<EXTRAS_STRING> extras;
Field<SCENE_MEMBERSHIP> 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<Sim&>(*this), i };
}
};
Sim mManager;
};
FILAMENT_UPCAST(NodeManager)
} // namespace gltfio
#endif // GLTFIO_FNODEMANAGER_H
+8 -16
View File
@@ -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 {
+83
View File
@@ -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 <utils/Log.h>
#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<CString> names) noexcept {
upcast(this)->setMorphTargetNames(ci, std::move(names));
}
const FixedCapacityVector<CString>& 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