This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/floorplan/3D/objects/MTLReader.h
2018-10-25 11:50:12 +02:00

146 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* © 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 MTLREADER_H
#define MTLREADER_H
#include <vector>
#include <unordered_map>
#include <string>
#include <fstream>
#include "../../../geo/Point2.h"
#include "../../../geo/Point3.h"
/**
* prase .mtl files
*/
class MTLReader {
public:
struct Material {
std::string textureFile = "";
Point3 diffuse = Point3(1,1,1);
float alpha = 1.0;
};
Material* cur = nullptr;
std::unordered_map<std::string, Material> map;
/** ctor. use readXYZ() */
MTLReader() {
;
}
/** read .mtl from the given file */
void readFile(const std::string& file) {
std::ifstream is(file);
std::string line;
while(getline(is, line)) {parseLine(line);}
is.close();
}
/** read mtl from the given data string (.mtl file contents) */
void readData(const char* data) {
readData(std::string(data));
}
/** read mtl from the given data string (.mtl file contents) */
void readData(const std::string& data) {
std::stringstream is(data);
std::string line;
while(getline(is, line)) {parseLine(line);}
}
/** get the given material */
const Material& getMaterial(const std::string& mat) const {
const auto& it = map.find(mat);
if (it == map.end()) {throw Exception("material not available");}
return it->second;
}
private:
template<typename Out>
void split(const std::string &s, char delim, Out result) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
*(result++) = item;
}
}
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
size_t end_pos = start_pos + from.length();
str.replace(start_pos, end_pos, to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
/** remove empty strings from the vector */
std::vector<std::string> nonEmpty(const std::vector<std::string>& src) {
std::vector<std::string> res;
for (const std::string& s : src) {
if (!s.empty()) {res.push_back(s);}
}
return res;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
/** parse one line of the .obj file */
void parseLine(std::string line) {
if (line.length() < 2) {return;}
// remove leading "#"
while (line[0] == ' ' || line[0] == '\t') {
line.erase(line.begin());
}
// remove other linebreaks
replaceAll(line, "\r", "");
const std::vector<std::string> tokens = nonEmpty(split(line, ' '));
const std::string token = tokens.front();
if ("newmtl" == token) {
const std::string id = tokens[1];
map[id] = Material();
cur = &map[id];
} else if ("map_Ka" == token) {
const std::string texFile = tokens[1];
cur->textureFile = texFile;
} else if ("map_Kd" == token) {
const std::string texFile = tokens[1];
cur->textureFile = texFile;
} else if ("Kd" == token) {
cur->diffuse.x = std::stof(tokens[1]);
cur->diffuse.y = std::stof(tokens[2]);
cur->diffuse.z = std::stof(tokens[3]);
} else if ("d" == token) {
cur->alpha = std::stof(tokens[1]);
}
}
};
#endif // MTLREADER_H