146 lines
3.2 KiB
C++
146 lines
3.2 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#ifndef FLOORPLAN_3D_OBJPOOL_H
|
||
#define FLOORPLAN_3D_OBJPOOL_H
|
||
|
||
#include <vector>
|
||
#include "../../../geo/Triangle3.h"
|
||
#include <unordered_map>
|
||
|
||
#include "OBJReader.h"
|
||
#include "../Obstacle3.h"
|
||
|
||
// LINUX ONLY
|
||
//#include <dirent.h>
|
||
//#include <stdio.h>
|
||
#include "../../../data/File.h"
|
||
|
||
|
||
#include "../../../misc/Debug.h"
|
||
|
||
|
||
namespace Floorplan3D {
|
||
|
||
/**
|
||
* load several named 3D models for quick re-use
|
||
*/
|
||
class OBJPool {
|
||
|
||
private:
|
||
|
||
static constexpr const char* name = "OBJ-Pool";
|
||
|
||
/** singleton */
|
||
OBJPool() {;}
|
||
|
||
bool initDone = false;
|
||
std::unordered_map<std::string, Obstacle3D> cache;
|
||
|
||
public:
|
||
|
||
/** singleton access */
|
||
static OBJPool& get() {
|
||
static OBJPool instance;
|
||
return instance;
|
||
}
|
||
|
||
/** init with *.obj data folder */
|
||
void init(const std::string& folder) {
|
||
|
||
scanFolder(folder);
|
||
initDone = true;
|
||
|
||
}
|
||
|
||
/** init with multiple *.obj data folder */
|
||
void init(const std::initializer_list<std::string>& folders) {
|
||
|
||
for (const std::string& folder : folders) {
|
||
try {
|
||
scanFolder(folder);
|
||
} catch (...) {;}
|
||
}
|
||
initDone = true;
|
||
|
||
}
|
||
|
||
/** get all triangles for the given object (if known) */
|
||
const Obstacle3D& getObject(const std::string& name) {
|
||
|
||
// ensure the cache is initialized
|
||
if (!initDone) {
|
||
throw Exception("OBJPool: not initialized. call init(folder) first");
|
||
}
|
||
|
||
static Obstacle3D empty;
|
||
|
||
// find the entry
|
||
const auto& it = cache.find(name);
|
||
if (it == cache.end()) {return empty;}
|
||
return it->second;
|
||
|
||
}
|
||
|
||
private:
|
||
|
||
/** scan the given folder for all *.obj files */
|
||
void scanFolder(const std::string& folder) {
|
||
|
||
FS::File d(folder);
|
||
if (!d.exists()) {
|
||
throw Exception("OBJPool: folder not found: " + folder);
|
||
}
|
||
|
||
for (const FS::File& f : d.listFiles()) {
|
||
std::string name = f.getFilename();
|
||
if (endsWith(name, ".obj")) {
|
||
//std::string name = entry.path().filename().string();
|
||
name = name.substr(0, name.length() - 4); // without extension
|
||
load(f.getPath(), name);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
inline bool endsWith(std::string const & value, std::string const & ending) {
|
||
if (ending.size() > value.size()) return false;
|
||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||
}
|
||
|
||
/** load the given .obj file into the cache */
|
||
void load(const std::string& absName, const std::string& name) {
|
||
|
||
OBJReader reader;
|
||
reader.readFile(absName);
|
||
//reader.readFile("/mnt/vm/paper/diss/code/IndoorMap/res/mdl/" + file + ".obj"); // todo
|
||
|
||
// create triangles
|
||
Obstacle3D obs;
|
||
for (const OBJReader::Object& obj : reader.getData().objects) {
|
||
for (const OBJReader::Face& face : obj.faces) {
|
||
const Triangle3 tria(face.vnt[0].vertex, face.vnt[1].vertex, face.vnt[2].vertex);
|
||
obs.triangles.push_back(tria);
|
||
}
|
||
}
|
||
|
||
Log::add(this->name, "loaded: " + absName + " [" + std::to_string(obs.triangles.size()) + " triangles]", true);
|
||
|
||
// store
|
||
cache[name] = obs;
|
||
|
||
}
|
||
|
||
};
|
||
|
||
}
|
||
|
||
#endif // FLOORPLAN_3D_OBJPOOL_H
|