Files
filament/libs/gltfio/src/FilamentAsset.cpp
Philip Rideout c7e4116154 gltfio: introduce support for extras strings.
This allows clients to obtain the extras strings for the asset and
for individual nodes.  Note that extras for buffer views, accessors, etc
are not supported, although C++ clients can access the raw cgltf data
directly if they need to.
2021-06-24 10:41:40 -07:00

302 lines
8.4 KiB
C++

/*
* Copyright (C) 2019 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 "FFilamentAsset.h"
#include <gltfio/Animator.h>
#include <utils/EntityManager.h>
#include <utils/Log.h>
#include <utils/NameComponentManager.h>
#include "Wireframe.h"
using namespace filament;
using namespace utils;
namespace gltfio {
FFilamentAsset::~FFilamentAsset() {
releaseSourceData();
// The only things we need to free in the instances are their animators.
// The union of all instance entities will be destroyed below.
for (FFilamentInstance* instance : mInstances) {
delete instance->animator;
delete instance;
}
delete mAnimator;
delete mWireframe;
mEngine->destroy(mRoot);
mEntityManager->destroy(mRoot);
for (auto entity : mEntities) {
// Destroy the entity's renderable, light, transform, and camera components.
mEngine->destroy(entity);
// Destroy the name component.
if (mNameManager) {
mNameManager->removeComponent(entity);
}
// Destroy the actual entity.
mEntityManager->destroy(entity);
}
for (auto mi : mMaterialInstances) {
mEngine->destroy(mi);
}
for (auto vb : mVertexBuffers) {
mEngine->destroy(vb);
}
for (auto bo : mBufferObjects) {
mEngine->destroy(bo);
}
for (auto ib : mIndexBuffers) {
mEngine->destroy(ib);
}
for (auto tx : mTextures) {
mEngine->destroy(tx);
}
}
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();
}
Animator* FFilamentAsset::getAnimator() noexcept {
if (!mAnimator) {
if (!mResourcesLoaded) {
slog.e << "Cannot create animator before resource loading." << io::endl;
return nullptr;
}
if (!mSourceAsset) {
slog.e << "Cannot create animator from frozen asset." << io::endl;
return nullptr;
}
mAnimator = new Animator(this, nullptr);
}
return mAnimator;
}
Entity FFilamentAsset::getWireframe() noexcept {
if (!mWireframe) {
mWireframe = new Wireframe(this);
}
return mWireframe->mEntity;
}
void FFilamentAsset::releaseSourceData() noexcept {
// To ensure that all possible memory is freed, we reassign to new containers rather than
// calling clear(). With many container types (such as robin_map), clearing is a fast
// operation that merely frees the storage for the items.
mMatInstanceCache = {};
mMeshCache = {};
mResourceUris = {};
mNodeMap = {};
mPrimitives = {};
mBufferSlots = {};
mTextureSlots = {};
mSourceAsset.reset();
for (FFilamentInstance* instance : mInstances) {
instance->nodeMap = {};
}
}
const char* FFilamentAsset::getName(utils::Entity entity) const noexcept {
if (mNameManager == nullptr) {
return nullptr;
}
auto nameInstance = mNameManager->getInstance(entity);
return nameInstance ? mNameManager->getName(nameInstance) : nullptr;
}
Entity FFilamentAsset::getFirstEntityByName(const char* name) noexcept {
const auto iter = mNameToEntity.find(name);
if (iter == mNameToEntity.end()) {
return {};
}
return iter->front();
}
size_t FFilamentAsset::getEntitiesByName(const char* name, Entity* entities,
size_t maxCount) const noexcept {
const auto iter = mNameToEntity.find(name);
if (iter == mNameToEntity.end()) {
return 0;
}
const auto& source = *iter;
if (entities == nullptr) {
return source.size();
}
maxCount = std::min(maxCount, source.size());
if (maxCount == 0) {
return 0;
}
size_t count = 0;
for (Entity entity : source) {
entities[count] = entity;
if (++count >= maxCount) {
return count;
}
}
return count;
}
size_t FFilamentAsset::getEntitiesByPrefix(const char* prefix, Entity* entities,
size_t maxCount) const noexcept {
const auto range = mNameToEntity.equal_prefix_range(prefix);
size_t count = 0;
for (auto iter = range.first; iter != range.second; ++iter) {
count += iter->size();
}
if (entities == nullptr) {
return count;
}
maxCount = std::min(maxCount, count);
if (maxCount == 0) {
return 0;
}
count = 0;
for (auto iter = range.first; iter != range.second; ++iter) {
const auto& source = *iter;
for (Entity entity : source) {
entities[count] = entity;
if (++count >= maxCount) {
return count;
}
}
}
return count;
}
size_t FilamentAsset::getEntityCount() const noexcept {
return upcast(this)->getEntityCount();
}
const Entity* FilamentAsset::getEntities() const noexcept {
return upcast(this)->getEntities();
}
const Entity* FilamentAsset::getLightEntities() const noexcept {
return upcast(this)->getLightEntities();
}
size_t FilamentAsset::getLightEntityCount() const noexcept {
return upcast(this)->getLightEntityCount();
}
const utils::Entity* FilamentAsset::getCameraEntities() const noexcept {
return upcast(this)->getCameraEntities();
}
size_t FilamentAsset::getCameraEntityCount() const noexcept {
return upcast(this)->getCameraEntityCount();
}
Entity FilamentAsset::getRoot() const noexcept {
return upcast(this)->getRoot();
}
Entity FilamentAsset::popRenderable() noexcept {
Entity result[1];
const bool empty = !popRenderables(result, 1);
return empty ? Entity() : result[0];
}
size_t FilamentAsset::popRenderables(Entity* result, size_t count) noexcept {
return upcast(this)->popRenderables(result, count);
}
size_t FilamentAsset::getMaterialInstanceCount() const noexcept {
return upcast(this)->getMaterialInstanceCount();
}
const MaterialInstance* const* FilamentAsset::getMaterialInstances() const noexcept {
return upcast(this)->getMaterialInstances();
}
MaterialInstance* const* FilamentAsset::getMaterialInstances() noexcept {
return upcast(this)->getMaterialInstances();
}
size_t FilamentAsset::getResourceUriCount() const noexcept {
return upcast(this)->getResourceUriCount();
}
const char* const* FilamentAsset::getResourceUris() const noexcept {
return upcast(this)->getResourceUris();
}
filament::Aabb FilamentAsset::getBoundingBox() const noexcept {
return upcast(this)->getBoundingBox();
}
const char* FilamentAsset::getName(Entity entity) const noexcept {
return upcast(this)->getName(entity);
}
Entity FilamentAsset::getFirstEntityByName(const char* name) noexcept {
return upcast(this)->getFirstEntityByName(name);
}
size_t FilamentAsset::getEntitiesByName(const char* name, Entity* entities,
size_t maxCount) const noexcept {
return upcast(this)->getEntitiesByName(name, entities, maxCount);
}
size_t FilamentAsset::getEntitiesByPrefix(const char* prefix, Entity* entities,
size_t maxCount) const noexcept {
return upcast(this)->getEntitiesByPrefix(prefix, entities, maxCount);
}
const char* FilamentAsset::getExtras(Entity entity) const noexcept {
return upcast(this)->getExtras(entity);
}
Animator* FilamentAsset::getAnimator() noexcept {
return upcast(this)->getAnimator();
}
Entity FilamentAsset::getWireframe() noexcept {
return upcast(this)->getWireframe();
}
Engine* FilamentAsset::getEngine() const noexcept {
return upcast(this)->getEngine();
}
void FilamentAsset::releaseSourceData() noexcept {
return upcast(this)->releaseSourceData();
}
const void* FilamentAsset::getSourceAsset() noexcept {
return upcast(this)->getSourceAsset();
}
FilamentInstance** FilamentAsset::getAssetInstances() noexcept {
return upcast(this)->getAssetInstances();
}
size_t FilamentAsset::getAssetInstanceCount() const noexcept {
return upcast(this)->getAssetInstanceCount();
}
} // namespace gltfio