载入中...
搜索中...
未找到
ModelLoader.cpp
浏览该文件的文档.
1// Loads ModelData through the unified resource cache (common/Resource.h).
2//
3// The cache key serializes ModelLoadOptions, so the same file decoded with
4// different options is distinct cached resources while identical requests
5// share one decoded Assimp scene.
6
8
10#include "common/Capability.h"
11#include "common/Exception.h"
12#include "common/Module.h"
13#include "common/Resource.h"
15#include "medialoader/Exception.h"
16#include "medialoader/model/ModelLoader.h"
18#include "model3d/Model3D.h"
19#include "model3d/ModelData.h"
20
21#include <cctype>
22#include <cstdlib>
23#include <string>
24
25namespace eve::model3d {
26namespace {
27
28std::string extensionOf(const std::string &path) {
29 const auto pos = path.find_last_of('.');
30 if (pos == std::string::npos) return {};
31 std::string ext = path.substr(pos);
32 for (char &c : ext) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
33 return ext;
34}
35
36bool isModelPath(const std::string &path) {
37 const std::string ext = extensionOf(path);
38 return ext == ".obj" || ext == ".fbx" || ext == ".gltf" || ext == ".glb" || ext == ".dae" ||
39 ext == ".3ds" || ext == ".blend" || ext == ".stl" || ext == ".ply" || ext == ".x" ||
40 ext == ".lwo" || ext == ".lws" || ext == ".md5mesh" || ext == ".md5anim" ||
41 ext == ".b3d" || ext == ".csm" || ext == ".irr" || ext == ".irrmesh" || ext == ".md2" ||
42 ext == ".md3" || ext == ".ms3d" || ext == ".smd" || ext == ".vta" || ext == ".bvh" ||
43 ext == ".ac" || ext == ".off" || ext == ".raw" || ext == ".ter" || ext == ".nff" ||
44 ext == ".ndo";
45}
46
47// Mirror of the option mapping in Model3D.cpp.
48medialoader::LoadOptions toMedialoader(const ModelLoadOptions &opt) {
49 medialoader::LoadOptions m;
50 m.triangulate = opt.triangulate;
51 m.generateNormalsIfMissing = opt.generateNormalsIfMissing;
52 m.joinIdenticalVertices = opt.joinIdenticalVertices;
53 m.flipUVs = opt.flipUVs;
54 m.improveCacheLocality = opt.improveCacheLocality;
55 return m;
56}
57
58int queryInt(const std::string &key, const std::string &name, int fallback) {
59 const auto q = key.find('?');
60 if (q == std::string::npos) return fallback;
61
62 std::string rest = key.substr(q + 1);
63 size_t pos = 0;
64 while (pos < rest.size()) {
65 const size_t amp = rest.find('&', pos);
66 const std::string pair =
67 rest.substr(pos, amp == std::string::npos ? std::string::npos : amp - pos);
68 const auto eq = pair.find('=');
69 if (eq != std::string::npos && pair.substr(0, eq) == name)
70 return std::atoi(pair.c_str() + eq + 1);
71 if (amp == std::string::npos) break;
72 pos = amp + 1;
73 }
74 return fallback;
75}
76
77bool queryBool(const std::string &key, const std::string &name, bool fallback) {
78 return queryInt(key, name, fallback ? 1 : 0) != 0;
79}
80
81ModelLoadOptions parseOptions(const std::string &key) {
82 ModelLoadOptions o;
83 o.triangulate = queryBool(key, "triangulate", o.triangulate);
84 o.generateNormalsIfMissing = queryBool(key, "normals", o.generateNormalsIfMissing);
85 o.joinIdenticalVertices = queryBool(key, "join", o.joinIdenticalVertices);
86 o.flipUVs = queryBool(key, "flipuv", o.flipUVs);
87 o.improveCacheLocality = queryBool(key, "cache", o.improveCacheLocality);
88 return o;
89}
90
91class ModelLoader : public eve::caps::IAssetReloader {
92public:
93 const char *reloadKind() const override { return "model"; }
94
95 bool handlesPath(const std::string &normPath) const override {
96 return isModelPath(eve::ResourceManager::pathOfKey(normPath));
97 }
98
99 eve::Resource *load(const std::string &key) override {
100 const std::string path = eve::ResourceManager::pathOfKey(key);
101 if (!isModelPath(path)) return nullptr;
102 const ModelLoadOptions options = parseOptions(key);
103
104 filesystem::Filesystem *fs =
105 ModuleManager::getInstance<filesystem::Filesystem>("Filesystem");
106 if (!fs) fs = filesystem::Filesystem::create();
107 if (!fs) return nullptr;
108
109 EveFileSystem eveFs(fs);
110 medialoader::ModelLoader loader(&eveFs);
111 try {
112 auto scene = loader.loadFromPath(path.c_str(), toMedialoader(options));
113 if (scene.empty())
114 throw eve::Exception("Could not load model: %s", path.c_str());
115 return new ModelData(std::move(scene), "file://" + path);
116 } catch (const medialoader::Exception &e) {
117 throw eve::Exception("%s", e.what());
118 }
119 }
120};
121
122struct Register {
123 Register() {
124 static ModelLoader loader;
126 }
127} g_register;
128
129} // namespace
130
131std::string modelCacheKey(const std::string &path, const ModelLoadOptions &options) {
132 std::string query;
133 query += "triangulate=" + std::to_string(options.triangulate ? 1 : 0);
134 query += "&normals=" + std::to_string(options.generateNormalsIfMissing ? 1 : 0);
135 query += "&join=" + std::to_string(options.joinIdenticalVertices ? 1 : 0);
136 query += "&flipuv=" + std::to_string(options.flipUVs ? 1 : 0);
137 query += "&cache=" + std::to_string(options.improveCacheLocality ? 1 : 0);
138 return eve::ResourceManager::makeKey(path, query);
139}
140
141ModelLoadOptions modelOptionsFromKey(const std::string &key) { return parseOptions(key); }
142
143} // namespace eve::model3d
uint32_t c
const char * name
Definition RockMesh.cpp:21
float m[16]
static std::string pathOfKey(const std::string &key)
The path part of a cache key (everything before the first '?').
Definition Resource.cpp:39
static std::string makeKey(const std::string &path, const std::string &query="")
Build a cache key from a path and optional ?query parameters.
Definition Resource.cpp:30
Resource is a game object that is managed by the ResourceManager. It can be loaded from a file or gen...
Definition Resource.h:35
I * query()
Definition Capability.h:77
std::string modelCacheKey(const std::string &path, const ModelLoadOptions &options)
Build a deterministic ResourceManager cache key for path + options.
ModelLoadOptions modelOptionsFromKey(const std::string &key)
Parse the options back out of a model cache key (inverse of modelCacheKey).
Toggles for the Assimp post-processing steps applied by medialoader on decode. All default to on (mat...
Definition Model3D.h:28