/* * 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 #include #include #include #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); } } 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); } 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