Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

repair gltf_viewer drag&drop #7327

Merged
merged 1 commit into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion libs/gltfio/include/gltfio/ResourceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
11 changes: 8 additions & 3 deletions libs/gltfio/src/ResourceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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));
}
Expand Down
102 changes: 74 additions & 28 deletions samples/gltf_viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
#include <imgui.h>
#include <filagui/ImGuiExtensions.h>

#include <cgltf.h>

#include <array>
#include <fstream>
#include <iostream>
Expand Down Expand Up @@ -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;

Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down