repair gltf_viewer drag&drop

Drag and dropping a gltf folder was broken:
- the handle didn't find the gltf file on drag&drop
- the ResourceLoader cached the asset path
- don't exit(1) when drag&dropping an invalid file
This commit is contained in:
Mathias Agopian
2023-11-01 15:02:43 -07:00
committed by Mathias Agopian
parent 46e6664c3d
commit 7d694ee85e
3 changed files with 86 additions and 32 deletions

View File

@@ -69,9 +69,12 @@ class UTILS_PUBLIC ResourceLoader {
public:
using BufferDescriptor = filament::backend::BufferDescriptor;
ResourceLoader(const ResourceConfiguration& config);
explicit ResourceLoader(const ResourceConfiguration& config);
~ResourceLoader();
void setConfiguration(const ResourceConfiguration& config);
/**
* Feeds the binary content of an external resource into the loader's URI cache.
*

View File

@@ -74,15 +74,15 @@ enum class CacheResult {
};
struct ResourceLoader::Impl {
Impl(const ResourceConfiguration& config) :
explicit Impl(const ResourceConfiguration& config) :
mEngine(config.engine),
mNormalizeSkinningWeights(config.normalizeSkinningWeights),
mGltfPath(config.gltfPath ? config.gltfPath : ""),
mUriDataCache(std::make_shared<UriDataCache>()) {}
Engine* const mEngine;
const bool mNormalizeSkinningWeights;
const std::string mGltfPath;
bool mNormalizeSkinningWeights;
std::string mGltfPath;
// User-provided resource data with URI string keys, populated with addResourceData().
// This is used on platforms without traditional file systems, such as Android, iOS, and WebGL.
@@ -320,6 +320,11 @@ ResourceLoader::~ResourceLoader() {
delete pImpl;
}
void ResourceLoader::setConfiguration(const ResourceConfiguration& config) {
pImpl->mNormalizeSkinningWeights = config.normalizeSkinningWeights;
pImpl->mGltfPath = config.gltfPath;
}
void ResourceLoader::addResourceData(const char* uri, BufferDescriptor&& buffer) {
pImpl->addResourceData(uri, std::move(buffer));
}

View File

@@ -53,6 +53,8 @@
#include <imgui.h>
#include <filagui/ImGuiExtensions.h>
#include <cgltf.h>
#include <array>
#include <fstream>
#include <iostream>
@@ -485,6 +487,57 @@ static void onClick(App& app, View* view, ImVec2 pos) {
});
}
static utils::Path getPathForAsset(std::string_view string) {
utils::Path filename{ string };
if (!filename.exists()) {
std::cerr << "file " << filename << " not found!" << std::endl;
return {};
}
if (filename.isDirectory()) {
auto files = filename.listContents();
for (const auto& file: files) {
if (file.getExtension() == "gltf" || file.getExtension() == "glb") {
filename = file;
break;
}
}
if (filename.isDirectory()) {
std::cerr << "no glTF file found in " << filename << std::endl;
return {};
}
}
return filename;
}
static bool checkAsset(const utils::Path& filename) {
// Peek at the file size to allow pre-allocation.
long const contentSize = static_cast<long>(getFileSize(filename.c_str()));
if (contentSize <= 0) {
std::cerr << "Unable to open " << filename << std::endl;
return false;
}
// Consume the glTF file.
std::ifstream in(filename.c_str(), std::ifstream::binary | std::ifstream::in);
std::vector<uint8_t> buffer(static_cast<unsigned long>(contentSize));
if (!in.read((char*) buffer.data(), contentSize)) {
std::cerr << "Unable to read " << filename << std::endl;
return false;
}
// Parse the glTF file and create Filament entities.
cgltf_options options{};
cgltf_data* sourceAsset;
cgltf_result result = cgltf_parse(&options, buffer.data(), contentSize, &sourceAsset);
if (result != cgltf_result_success) {
slog.e << "Unable to parse glTF file." << io::endl;
return false;
}
return true;
};
int main(int argc, char** argv) {
App app;
@@ -496,24 +549,10 @@ int main(int argc, char** argv) {
utils::Path filename;
int const num_args = argc - optionIndex;
if (num_args >= 1) {
filename = argv[optionIndex];
if (!filename.exists()) {
std::cerr << "file " << filename << " not found!" << std::endl;
filename = getPathForAsset(argv[optionIndex]);
if (filename.isEmpty()) {
return 1;
}
if (filename.isDirectory()) {
auto files = filename.listContents();
for (const auto& file : files) {
if (file.getExtension() == "gltf" || file.getExtension() == "glb") {
filename = file;
break;
}
}
if (filename.isDirectory()) {
std::cerr << "no glTF file found in " << filename << std::endl;
return 1;
}
}
}
auto loadAsset = [&app](const utils::Path& filename) {
@@ -534,14 +573,14 @@ int main(int argc, char** argv) {
// Parse the glTF file and create Filament entities.
app.asset = app.assetLoader->createAsset(buffer.data(), buffer.size());
app.instance = app.asset->getInstance();
buffer.clear();
buffer.shrink_to_fit();
if (!app.asset) {
std::cerr << "Unable to parse " << filename << std::endl;
exit(1);
}
app.instance = app.asset->getInstance();
buffer.clear();
buffer.shrink_to_fit();
};
auto loadResources = [&app] (const utils::Path& filename) {
@@ -559,6 +598,8 @@ int main(int argc, char** argv) {
app.resourceLoader->addTextureProvider("image/png", app.stbDecoder);
app.resourceLoader->addTextureProvider("image/jpeg", app.stbDecoder);
app.resourceLoader->addTextureProvider("image/ktx2", app.ktxDecoder);
} else {
app.resourceLoader->setConfiguration(configuration);
}
if (!app.resourceLoader->asyncBeginLoad(app.asset)) {
@@ -1021,14 +1062,19 @@ int main(int argc, char** argv) {
filamentApp.animate(animate);
filamentApp.resize(resize);
filamentApp.setDropHandler([&] (std::string_view path) {
app.resourceLoader->asyncCancelLoad();
app.resourceLoader->evictResourceData();
app.viewer->removeAsset();
app.assetLoader->destroyAsset(app.asset);
loadAsset(path);
loadResources(path);
app.viewer->setAsset(app.asset, app.instance);
filamentApp.setDropHandler([&](std::string_view path) {
utils::Path const filename = getPathForAsset(path);
if (!filename.isEmpty()) {
if (checkAsset(filename)) {
app.resourceLoader->asyncCancelLoad();
app.resourceLoader->evictResourceData();
app.viewer->removeAsset();
app.assetLoader->destroyAsset(app.asset);
loadAsset(filename);
loadResources(filename);
app.viewer->setAsset(app.asset, app.instance);
}
}
});
filamentApp.run(app.config, setup, cleanup, gui, preRender, postRender);