Introduce gltfio::NodeManager, remove some robin_map. (#5522)
* Introduce gltfio::NodeManager, remove some robin_map. * Incorporate code review feedback.
This commit is contained in:
@@ -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
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user