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/FloorplanMesh.h

357 lines
11 KiB
C++
Raw Permalink 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 FLOORPLAN_3D_FLOORPLANMESH_H
#define FLOORPLAN_3D_FLOORPLANMESH_H
#include "Obstacle3.h"
#include "../../geo/BBox3.h"
#include <fstream>
namespace Floorplan3D {
/**
* meshed version of the floorplan
*/
struct FloorplanMesh {
std::vector<Obstacle3D> elements;
BBox3 getBBox() const {
BBox3 bb;
for (const Obstacle3D& o : elements) {
for (const Triangle3& t : o.triangles) {
bb.add(t.p1);
bb.add(t.p2);
bb.add(t.p3);
}
}
return bb;
}
void operator -= (const Point3 p) {
for (Obstacle3D& o : elements) {
for (Triangle3& t : o.triangles) {
t -= p;
}
}
}
/** export as OBJ file */
void exportOBJsimple(const std::string& file) {
std::ofstream out(file.c_str());
out << toOBJsimple();
out.close();
}
/** export as OBJ file */
void exportOBJcomplex(const std::string& file, const std::string& nameOnly) {
std::ofstream outOBJ((file+".obj").c_str());
std::ofstream outMTL((file+".mtl").c_str());
OBJData data = toOBJ(nameOnly);
outOBJ << data.obj;
outMTL << data.mtl;
outOBJ.close();
outMTL.close();
}
/** export as PLY file */
void exportPLY(const std::string& file) {
std::ofstream out(file.c_str());
out << toPLY();
out.close();
}
/** DEBUG: convert to .obj file code for exporting */
std::string toOBJsimple() {
int nVerts = 1;
std::string res;
// write each obstacle
for (const Obstacle3D& o : elements) {
// write the vertices
for (const Triangle3& t : o.triangles) {
res += "v " + std::to_string(t.p1.x) + " " + std::to_string(t.p1.y) + " " + std::to_string(t.p1.z) + "\n";
res += "v " + std::to_string(t.p2.x) + " " + std::to_string(t.p2.y) + " " + std::to_string(t.p2.z) + "\n";
res += "v " + std::to_string(t.p3.x) + " " + std::to_string(t.p3.y) + " " + std::to_string(t.p3.z) + "\n";
}
}
// write each obstacle
for (const Obstacle3D& o : elements) {
// write the faces
for (size_t i = 0; i < o.triangles.size(); ++i) {
res += "f " + std::to_string(nVerts+0) + " " + std::to_string(nVerts+1) + " " + std::to_string(nVerts+2) + "\n";
nVerts += 3;
}
}
// done
return res;
}
struct OBJData {
std::string obj;
std::string mtl;
};
/** DEBUG: convert to .obj file code for exporting */
OBJData toOBJ(const std::string name) {
const BBox3 bb = getBBox();
const float ox = bb.getCenter().x;
const float oy = bb.getCenter().y;
bool swapYZ = true;
int nVerts = 1;
int nObjs = 0;
OBJData res;
// write material file
for (size_t idx = 0; idx < mats.size(); ++idx) {
const Material& mat = mats[idx];
res.mtl += "newmtl mat_" + mat.name + "\n";
res.mtl += "Ka 0.000 0.000 0.000 \n"; // ambient
res.mtl += "Kd " + std::to_string(mat.r/255.0f) + " " + std::to_string(mat.g/255.0f) + " " + std::to_string(mat.b/255.0f) + "\n";
res.mtl += "Ks 0.000 0.000 0.000 \n";
res.mtl += "d " + std::to_string(mat.a/255.0f) + "\n"; // alpha
res.mtl += "Tr " + std::to_string(1.0f-mat.a/255.0f) + "\n"; // inv-alpha
res.mtl += "illum 2 \n";
res.mtl += "\n";
}
// use material file
res.obj += "mtllib " + name + ".mtl" + "\n";
// write each obstacle
for (const Obstacle3D& o : elements) {
// write the vertices
for (const Triangle3& t : o.triangles) {
if (!swapYZ) {
res.obj += "v " + std::to_string(t.p1.x-ox) + " " + std::to_string(t.p1.y-oy) + " " + std::to_string(t.p1.z) + "\n";
res.obj += "v " + std::to_string(t.p2.x-ox) + " " + std::to_string(t.p2.y-oy) + " " + std::to_string(t.p2.z) + "\n";
res.obj += "v " + std::to_string(t.p3.x-ox) + " " + std::to_string(t.p3.y-oy) + " " + std::to_string(t.p3.z) + "\n";
} else {
res.obj += "v " + std::to_string(t.p1.x-ox) + " " + std::to_string(t.p1.z) + " " + std::to_string(t.p1.y-oy) + "\n";
res.obj += "v " + std::to_string(t.p3.x-ox) + " " + std::to_string(t.p3.z) + " " + std::to_string(t.p3.y-oy) + "\n";
res.obj += "v " + std::to_string(t.p2.x-ox) + " " + std::to_string(t.p2.z) + " " + std::to_string(t.p2.y-oy) + "\n";
}
}
}
// write each obstacle
for (const Obstacle3D& o : elements) {
// create a new group
//res.obj += "g elem_" + std::to_string(++nObjs) + "\n";
// create a new object
res.obj += "o elem_" + std::to_string(++nObjs) + "\n";
// group's material
res.obj += "usemtl mat_" + getMaterial(o).name + "\n";
// write the group's faces
for (size_t i = 0; i < o.triangles.size(); ++i) {
res.obj += "f " + std::to_string(nVerts+0) + " " + std::to_string(nVerts+1) + " " + std::to_string(nVerts+2) + "\n";
nVerts += 3;
}
}
// done
return res;
}
/** convert to .ply file format */
std::string toPLY() const {
std::stringstream res;
res << "ply\n";
res << "format ascii 1.0\n";
int faces = 0;
int vertices = 0;
for (const Obstacle3D& obs : elements) {
vertices += obs.triangles.size() * 3;
faces += obs.triangles.size();
}
res << "element material " << mats.size() << "\n";
res << "property uchar red\n";
res << "property uchar green\n";
res << "property uchar blue\n";
res << "property uchar alpha\n";
res << "element vertex " << vertices << "\n";
res << "property float x\n";
res << "property float y\n";
res << "property float z\n";
res << "property float nx\n";
res << "property float ny\n";
res << "property float nz\n";
res << "property uchar red\n";
res << "property uchar green\n";
res << "property uchar blue\n";
res << "property uchar alpha\n";
res << "property int material_index\n";
res << "element face " << faces << "\n";
res << "property list uchar int vertex_indices\n";
res << "end_header\n";
for (const Material& mat : mats) {
res << mat.r << " " << mat.g << " " << mat.b << " " << mat.a << "\n";
}
for (const Obstacle3D& obs : elements) {
const int matIdx = getMaterialIdx(obs);
const Material& mat = mats[matIdx];
for (const Triangle3& tria : obs.triangles) {
const Point3 n = cross(tria.p2-tria.p1, tria.p3-tria.p1).normalized();
res << tria.p1.x << " " << tria.p1.y << " " << tria.p1.z << " " << n.x << " " << n.y << " " << n.z << " " << mat.r << " " << mat.g << " " << mat.b << " " << mat.a << " " << matIdx << "\n";
res << tria.p2.x << " " << tria.p2.y << " " << tria.p2.z << " " << n.x << " " << n.y << " " << n.z << " " << mat.r << " " << mat.g << " " << mat.b << " " << mat.a << " " << matIdx << "\n";
res << tria.p3.x << " " << tria.p3.y << " " << tria.p3.z << " " << n.x << " " << n.y << " " << n.z << " " << mat.r << " " << mat.g << " " << mat.b << " " << mat.a << " " << matIdx << "\n";
}
}
int vidx = 0;
for (const Obstacle3D& obs : elements) {
for (const Triangle3& tria : obs.triangles) {
(void) tria;
res << "3 " << (vidx+0) << " " << (vidx+1) << " " << (vidx+2) << "\n";
vidx += 3;
}
}
// done
return res.str();
}
struct Material {
int r, g, b, a;
std::string name;
Material(int r, int g, int b, int a) : r(r), g(g), b(b), a(a) {;}
Material(int r, int g, int b, int a, const std::string& name) : r(r), g(g), b(b), a(a), name(name) {;}
};
// // material
// std::vector<Material> mats = {
// Material(0,128,0,255), // ground outdoor
// Material(64,64,64,255), // ground outdoor
// Material(255,96,96,255), // stair
// Material(128,128,128,255), // concrete
// Material(64,128,255,64), // glass
// Material(200,200,200,255), // default
// };
// int getMaterial(const Obstacle3D& o) const {
// if (o.type == Obstacle3D::Type::GROUND_OUTDOOR) {return 0;}
// if (o.type == Obstacle3D::Type::GROUND_INDOOR) {return 1;}
// if (o.type == Obstacle3D::Type::STAIR) {return 2;}
// if (o.mat == Floorplan::Material::CONCRETE) {return 3;}
// if (o.mat == Floorplan::Material::GLASS) {return 4;}
// return 5;
// }
std::vector<Material> mats = {
Material(255,0,0,255 , "error"), // error
Material(0,128,0,255 , "ground_outdoor"), // ground outdoor
Material(64,64,64,255 , "ground_indoor"), // ground outdoor
Material(105,105,105,255, "stair"), // stair
Material(220,220,220,255, "handrail"), // handrail
Material(200,200,255,96 , "door_glass"), // door (glass)
Material(140,140,140,255, "door_wood"), // door (wood)
Material(135,135,135,255, "concrete"), // concrete
Material(240,240,255,96 , "glass"), // glass
Material(170,170,255,96 , "glass_metallized"), // glass (metallized)
Material(170,120,60,255 , "wood"), // wood
Material(200,200,200,255, "drywall"), // drywall
Material(255,255,255,255, "metal"), // metal
Material(255,255,255,255, "object"), // object
Material(235,235,235,255, "dafult"), // default
};
int getMaterialIdx(const Obstacle3D& o) const {
if (o.type == Floorplan3D::Obstacle3D::Type::ERROR) {return 0;}
if (o.type == Floorplan3D::Obstacle3D::Type::GROUND_OUTDOOR) {return 1;}
if (o.type == Floorplan3D::Obstacle3D::Type::GROUND_INDOOR) {return 2;}
if (o.type == Floorplan3D::Obstacle3D::Type::STAIR) {return 3;}
if (o.type == Floorplan3D::Obstacle3D::Type::HANDRAIL) {return 4;}
if (o.type == Floorplan3D::Obstacle3D::Type::OBJECT) {return 12;}
if (o.type == Floorplan3D::Obstacle3D::Type::DOOR && o.mat == Floorplan::Material::GLASS) {return 5;}
if (o.type == Floorplan3D::Obstacle3D::Type::DOOR) {return 6;}
if (o.mat == Floorplan::Material::CONCRETE) {return 7;}
if (o.mat == Floorplan::Material::GLASS) {return 8;}
if (o.mat == Floorplan::Material::METALLIZED_GLAS) {return 9;}
if (o.mat == Floorplan::Material::WOOD) {return 10;}
if (o.mat == Floorplan::Material::DRYWALL) {return 11;}
if (o.mat == Floorplan::Material::METAL) {return 12;}
return 13;
}
const Material& getMaterial(const Obstacle3D& o) const {
const int idx = getMaterialIdx(o);
return mats[idx];
}
// Color getColor(const Obstacle3D& o) const {
// if (o.type == Obstacle3D::Type::GROUND_OUTDOOR) {return Color(0,128,0,255);}
// if (o.type == Obstacle3D::Type::GROUND_INDOOR) {return Color(64,64,64,255);}
// if (o.mat == Floorplan::Material::CONCRETE) {return Color(128,128,128,255);}
// if (o.mat == Floorplan::Material::GLASS) {return Color(128,128,255,64);}
// return Color(200,200,200,255);
// }
};
}
#endif // FLOORPLAN_3D_FLOORPLANMESH_H