pleascach/Scene/March.hpp

169 lines
4.2 KiB
C++

#pragma once
/* file format for storing raymarched scene for dynamic SDF */
#include <Scene/Object.hpp>
#include <util/log.hpp>
#include <fstream>
#include <map>
namespace March {
static std::vector<Object> readFile(const std::string& fname, std::map<std::string, int>& name_map) {
/* this should be rewritten once we are loading more than 250 objects */
std::ifstream in(fname);
std::vector<Object> ret;
Object tmp;
std::string name;
std::string type;
int id = 0;
while(in >> type) {
Log::info("Object Type: %s\n", type.c_str());
char dummy;
in >> dummy;
if (dummy != '(') {
Log::error("Expected '(', found %c\n", dummy);
}
in >> tmp.center.x;
in >> tmp.center.y;
in >> tmp.center.z;
in >> dummy;
if (dummy != ')') {
Log::error("Expected ')', found %c\n", dummy);
}
if (type == "SPHERE") {
tmp.shape = Shape::eSPHERE;
char dummy;
in >> dummy;
if (dummy != '(') {
Log::error("Expected '(', found %c\n", dummy);
}
in >> tmp.dimensions.x;
in >> dummy;
if (dummy != ')') {
Log::error("Expected ')', found %c\n", dummy);
}
} else if (type == "BOX") {
tmp.shape = Shape::eBOX;
char dummy;
in >> dummy;
if (dummy != '(') {
Log::error("Expected '(', found %c\n", dummy);
}
in >> tmp.dimensions.x;
in >> tmp.dimensions.y;
in >> tmp.dimensions.z;
in >> dummy;
if (dummy != ')') {
Log::error("Expected ')', found %c\n", dummy);
}
} else {
Log::error("Expected type name, but not recognized %s!\n", type.c_str());
}
in >> name;
if (name_map.find(name) == name_map.end())
name_map[name] = id++;
tmp.id = name_map[name];
ret.push_back(tmp);
}
return ret;
}
static std::string find_name(const std::map<std::string, int>& map, const int id, bool& found) {
found = false;
std::string name = "##";
for (const auto& p : map) {
if (p.second == id) {
found = true;
name = p.first;
break;
}
}
return name;
}
static void add_sphere(const std::string& name, glm::vec3 center, float rad, Renderer* ren) {
unsigned int id = 0xDEADBEEF;
if (ren->scene_map.find(name) == ren->scene_map.end()) {
/* start iterating from the number of total objects, which will break immediately if stuff is deleted and new things added before saving, so please change this */
id = ren->scene_map.size();
ren->scene_map[name] = id;
} else {
id = ren->scene_map[name];
}
ren->objects.push_back(Object{
.center = glm::vec4(center.x, center.y, center.z, 0.0),
.dimensions = glm::vec4(rad),
.id = id,
.shape = eSPHERE,
});
}
static void add_box(const std::string& name, glm::vec3 center, glm::vec3 dim, Renderer* ren) {
unsigned int id = 0xDEADBEEF;
if (ren->scene_map.find(name) == ren->scene_map.end()) {
/* start iterating from the number of total objects, which will break immediately if stuff is deleted and new things added before saving, so please change this */
id = ren->scene_map.size();
ren->scene_map[name] = id;
} else {
id = ren->scene_map[name];
}
ren->objects.push_back(Object{
.center = glm::vec4(center.x, center.y, center.z, 0.0),
.dimensions = glm::vec4(dim.x, dim.y, dim.z, 0.0),
.id = id,
.shape = eBOX,
});
}
static void writeFile(const std::string& fname, const std::vector<Object>& objs, const std::map<std::string, int>& map) {
std::ofstream out(fname);
const char* shape_names[] = {
"SPHERE",
"BOX",
"PLANE",
};
int anon = 0;
for (const auto& obj : objs) {
out << shape_names[obj.shape] << " ( " << obj.center.x << " " << obj.center.y << " " << obj.center.z << " ) ( ";
switch (obj.shape) {
case eSPHERE:
out << obj.dimensions.x << " ";
break;
case eBOX:
out << obj.dimensions.x << " "
<< obj.dimensions.y << " "
<< obj.dimensions.z << " ";
break;
case ePLANE:
out << obj.dimensions.x << " "
<< obj.dimensions.y << " "
<< obj.dimensions.z << " ";
break;
}
bool found = false;
auto name = find_name(map, obj.id, found);
if (!found || name[0] == '#') {
name = std::string("#") + std::to_string(anon++);
}
out << ") " << name << std::endl;
}
out.close();
}
};