worked on 3d models within map
adjusted grid factory adjusted nav mesh factory minoor changes/fixes new helper classes refactoring
This commit is contained in:
@@ -18,6 +18,16 @@ namespace Ray3D {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
enum Part {
|
||||
CUBE_TOP = 1,
|
||||
CUBE_BOTTOM = 2,
|
||||
CUBE_LEFT = 4,
|
||||
CUBE_RIGHT = 8,
|
||||
CUBE_FRONT = 16,
|
||||
CUBE_BACK = 32,
|
||||
};
|
||||
|
||||
// Cube (const Point3 p1, const Point3 p2, const Point3 p3, const Point3 p4, const float h) {
|
||||
//// const Point3 ph(0,0,h);
|
||||
//// addQuad(p1+ph, p2+ph, p3+ph, p4+ph); // top
|
||||
@@ -30,8 +40,8 @@ namespace Ray3D {
|
||||
// }
|
||||
|
||||
/** ctor with position, size and rotation */
|
||||
Cube(const Point3 pos, const Point3 size, const Point3 rot_deg, const bool topAndBottom = true) {
|
||||
unitCube(topAndBottom);
|
||||
Cube(const Point3 pos, const Point3 size, const Point3 rot_deg, const Part parts = (Part)63) {
|
||||
unitCube(parts);
|
||||
transform(pos, size, rot_deg);
|
||||
}
|
||||
|
||||
@@ -50,8 +60,10 @@ namespace Ray3D {
|
||||
return res;
|
||||
}
|
||||
|
||||
static Cube unit() {
|
||||
return Cube();
|
||||
static Cube unit(const Part parts = (Part) 63) {
|
||||
Cube cube;
|
||||
cube.unitCube(parts);
|
||||
return cube;
|
||||
}
|
||||
|
||||
/** cube from 8 vertices (upper 4, lower 4) */
|
||||
@@ -77,72 +89,73 @@ namespace Ray3D {
|
||||
private:
|
||||
|
||||
/** build unit-cube faces */
|
||||
void unitCube(const bool topAndBottom) {
|
||||
void unitCube(const Part parts) {
|
||||
|
||||
const float s = 1.0f;
|
||||
|
||||
|
||||
|
||||
// left?
|
||||
addQuad(
|
||||
Point3(+s, -s, -s),
|
||||
Point3(+s, -s, +s),
|
||||
Point3(-s, -s, +s),
|
||||
Point3(-s, -s, -s)
|
||||
);
|
||||
if (parts & CUBE_LEFT) {
|
||||
addQuad(
|
||||
Point3(+s, -s, -s),
|
||||
Point3(+s, -s, +s),
|
||||
Point3(-s, -s, +s),
|
||||
Point3(-s, -s, -s)
|
||||
);
|
||||
}
|
||||
|
||||
// right?
|
||||
addQuad(
|
||||
Point3(-s, +s, -s),
|
||||
Point3(-s, +s, +s),
|
||||
Point3(+s, +s, +s),
|
||||
Point3(+s, +s, -s)
|
||||
);
|
||||
if (parts & CUBE_RIGHT) {
|
||||
addQuad(
|
||||
Point3(-s, +s, -s),
|
||||
Point3(-s, +s, +s),
|
||||
Point3(+s, +s, +s),
|
||||
Point3(+s, +s, -s)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// small side
|
||||
if (1 == 1) {
|
||||
|
||||
// front
|
||||
// front
|
||||
if (parts & CUBE_FRONT) {
|
||||
addQuad(
|
||||
Point3(-s, -s, -s),
|
||||
Point3(-s, -s, +s),
|
||||
Point3(-s, +s, +s),
|
||||
Point3(-s, +s, -s)
|
||||
);
|
||||
}
|
||||
|
||||
// read
|
||||
// back
|
||||
if (parts & CUBE_BACK) {
|
||||
addQuad(
|
||||
Point3(+s, +s, -s),
|
||||
Point3(+s, +s, +s),
|
||||
Point3(+s, -s, +s),
|
||||
Point3(+s, -s, -s)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (topAndBottom) {
|
||||
|
||||
// top
|
||||
// top
|
||||
if (parts & CUBE_TOP) {
|
||||
addQuad(
|
||||
Point3(+s, +s, +s),
|
||||
Point3(-s, +s, +s),
|
||||
Point3(-s, -s, +s),
|
||||
Point3(+s, -s, +s)
|
||||
);
|
||||
}
|
||||
|
||||
// bottom
|
||||
// bottom
|
||||
if (parts & CUBE_BOTTOM) {
|
||||
addQuad(
|
||||
Point3(+s, -s, -s),
|
||||
Point3(-s, -s, -s),
|
||||
Point3(-s, +s, -s),
|
||||
Point3(+s, +s, -s)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
127
wifi/estimate/ray3/MTLReader.h
Normal file
127
wifi/estimate/ray3/MTLReader.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#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 .obj 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 obj from the given data string (.obj 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 ("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
|
||||
@@ -18,7 +18,7 @@ namespace Ray3D {
|
||||
*/
|
||||
class ModelFactory {
|
||||
|
||||
private:
|
||||
public:
|
||||
|
||||
bool exportCeilings = true;
|
||||
bool exportObstacles = true;
|
||||
@@ -26,9 +26,12 @@ namespace Ray3D {
|
||||
bool fancyStairs = true;
|
||||
bool exportHandrails = true;
|
||||
bool exportDoors = true;
|
||||
bool doorsOpen = true;
|
||||
bool exportAboveDoors = true;
|
||||
bool doorsOpen = false;
|
||||
bool exportObjects = true;
|
||||
bool exportWallTops = false;
|
||||
Cube::Part cubeParts = (Cube::Part) 63; // leftright,topbottom,rearfront
|
||||
|
||||
std::vector<Floorplan::Floor*> exportFloors;
|
||||
|
||||
/** the to-be-exported map */
|
||||
@@ -233,7 +236,9 @@ namespace Ray3D {
|
||||
}
|
||||
//std::vector<Obstacle3D> tmp = getDoorAbove(f, door);
|
||||
//res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
res.push_back(getDoorAbove(f, door));
|
||||
if (exportAboveDoors) {
|
||||
res.push_back(getDoorAbove(f, door));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,8 +279,8 @@ namespace Ray3D {
|
||||
const float deg = rad * 180 / M_PI;
|
||||
|
||||
// cube's destination center
|
||||
const float cenZ = (!aboveDoor) ? (fpos.z1 + fpos.height/2) : (fpos.z2 - (fpos.height - aboveDoor->height) / 2);
|
||||
const float height = (!aboveDoor) ? (fpos.height) : (fpos.height - aboveDoor->height);
|
||||
const double height = (!aboveDoor) ? (fpos.height) : (fpos.height - aboveDoor->height);
|
||||
const double cenZ = (!aboveDoor) ? (fpos.z1 + height/2) : (fpos.z1 + aboveDoor->height + height/2);// (fpos.z2 - (fpos.height - aboveDoor->height) / 2);
|
||||
const Point3 pos(cen2.x, cen2.y, cenZ);
|
||||
|
||||
// div by 2.01 to prevent overlapps and z-fighting
|
||||
@@ -286,7 +291,7 @@ namespace Ray3D {
|
||||
const Point3 rot(0,0,deg);
|
||||
|
||||
// build
|
||||
Cube cube(pos, size, rot);
|
||||
Cube cube(pos, size, rot, cubeParts);
|
||||
|
||||
// done
|
||||
Obstacle3D res(getType(fol), fol->material);
|
||||
@@ -359,7 +364,7 @@ namespace Ray3D {
|
||||
const float sz = door->height / 2.01f; // prevent overlaps
|
||||
const Point3 size(sx, sy, sz);
|
||||
|
||||
Cube cube = Cube::unit();
|
||||
Cube cube = Cube::unit(cubeParts);
|
||||
cube.transform(mat);
|
||||
cube.transform(pos, size, rot);
|
||||
res.triangles = cube.getTriangles();
|
||||
|
||||
@@ -91,9 +91,11 @@ namespace Ray3D {
|
||||
|
||||
// create triangles
|
||||
Obstacle3D obs;
|
||||
for (const OBJReader::Face& face : reader.getData().faces) {
|
||||
const Triangle3 tria(face.vnt[0].vertex, face.vnt[1].vertex, face.vnt[2].vertex);
|
||||
obs.triangles.push_back(tria);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// store
|
||||
|
||||
@@ -14,7 +14,6 @@ class OBJReader {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/** group vertex+normal+texture */
|
||||
struct VNT {
|
||||
int idxVertex;
|
||||
@@ -31,15 +30,26 @@ public:
|
||||
Face(VNT v1, VNT v2, VNT v3) : vnt({v1,v2,v3}) {;}
|
||||
};
|
||||
|
||||
/** one object within the file */
|
||||
struct Object {
|
||||
std::string material;
|
||||
std::string name;
|
||||
std::vector<Face> faces;
|
||||
};
|
||||
|
||||
/** internal data */
|
||||
struct Data {
|
||||
std::vector<Point3> vertices;
|
||||
std::vector<Point2> texCoords;
|
||||
std::vector<Point3> normals;
|
||||
std::vector<Face> faces;
|
||||
std::vector<std::string> materialFiles;
|
||||
std::vector<Object> objects;
|
||||
Object& curObj() {
|
||||
if (objects.empty()) {objects.push_back(Object());}
|
||||
return objects.back();
|
||||
}
|
||||
} data;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** ctor. use readXYZ() */
|
||||
@@ -68,6 +78,24 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template<typename Out>
|
||||
void split(const std::string &s, char delim, Out result) {
|
||||
std::stringstream ss(s);
|
||||
@@ -84,20 +112,33 @@ private:
|
||||
}
|
||||
|
||||
/** parse one line of the .obj file */
|
||||
void parseLine(const std::string& line) {
|
||||
void parseLine(std::string line) {
|
||||
|
||||
if (line.length() < 2) {return;}
|
||||
|
||||
const std::vector<std::string> tokens = split(line, ' ');
|
||||
// remove other linebreaks
|
||||
replaceAll(line, "\r", "");
|
||||
|
||||
const std::vector<std::string> tokens = nonEmpty(split(line, ' '));
|
||||
const std::string token = tokens.front();
|
||||
|
||||
if ("v" == token) {parseVertex(tokens);}
|
||||
if ("vt" == token) {parseTexCoord(tokens);}
|
||||
if ("vn" == token) {parseNormal(tokens);}
|
||||
if ("f" == token) {parseFace(tokens);}
|
||||
if ("mtllib" == token) {data.materialFiles.push_back(tokens[1]);}
|
||||
if ("usemtl" == token) {data.curObj().material = tokens[1];}
|
||||
if ("v" == token) {parseVertex(tokens);}
|
||||
if ("vt" == token) {parseTexCoord(tokens);}
|
||||
if ("vn" == token) {parseNormal(tokens);}
|
||||
if ("f" == token) {parseFace(tokens);}
|
||||
if ("g" == token) {newObject(tokens[1]);}
|
||||
|
||||
}
|
||||
|
||||
/** allocate a new object */
|
||||
void newObject(const std::string& name) {
|
||||
Object o;
|
||||
o.name = name;
|
||||
data.objects.push_back(o);
|
||||
}
|
||||
|
||||
/** parse one vertex from the tokenizer */
|
||||
void parseVertex(const std::vector<std::string>& t) {
|
||||
const float x = std::stof(t[1]);
|
||||
@@ -135,18 +176,20 @@ private:
|
||||
|
||||
++numVertices;
|
||||
const std::string v = vtn[0];
|
||||
const std::string vt = (vtn.size() > 1) ? (vtn[1]) : ("");
|
||||
const std::string vn = (vtn.size() > 2) ? (vtn[2]) : ("");
|
||||
//const std::string vt = t2.getToken('/', false);
|
||||
//const std::string vn = t2.getToken('/', false);
|
||||
|
||||
// create a new vertex/normal/texture combination
|
||||
VNT vnt;
|
||||
vnt.idxVertex = (std::stoi(v) - 1);
|
||||
//vnt.idxNormal = (vn.empty()) ? (-1) : (std::stoi(vn) - 1);
|
||||
//vnt.idxTexture = (vt.empty()) ? (-1) : (std::stoi(vt) - 1);
|
||||
vnt.idxNormal = (vn.empty()) ? (-1) : (std::stoi(vn) - 1);
|
||||
vnt.idxTexture = (vt.empty()) ? (-1) : (std::stoi(vt) - 1);
|
||||
|
||||
if (vnt.idxVertex >= 0) {vnt.vertex = data.vertices[vnt.idxVertex];}
|
||||
//if (vnt.idxNormal >= 0) {vnt.normal = data.normals[vnt.idxNormal];}
|
||||
//if (vnt.idxTexture >= 0) {vnt.texture = data.texCoords[vnt.idxTexture];}
|
||||
if (vnt.idxNormal >= 0) {vnt.normal = data.normals[vnt.idxNormal];}
|
||||
if (vnt.idxTexture >= 0) {vnt.texture = data.texCoords[vnt.idxTexture];}
|
||||
|
||||
indices.push_back(vnt);
|
||||
|
||||
@@ -156,7 +199,7 @@ private:
|
||||
// see: http://www.mathopenref.com/polygontriangles.html
|
||||
for (int i = 1; i < (int) indices.size()-1; ++i) {
|
||||
Face face(indices[0], indices[1], indices[i+1]);
|
||||
data.faces.push_back(face);
|
||||
data.curObj().faces.push_back(face);
|
||||
}
|
||||
|
||||
// sanity check
|
||||
|
||||
@@ -59,6 +59,28 @@ namespace Ray3D {
|
||||
return copy;
|
||||
}
|
||||
|
||||
/** get all triangle-edge-points (x,y) within the obstacle */
|
||||
std::vector<Point2> getPoints2D() const {
|
||||
std::vector<Point2> res;
|
||||
for (const Triangle3& tria : triangles) {
|
||||
res.push_back(tria.p1.xy());
|
||||
res.push_back(tria.p2.xy());
|
||||
res.push_back(tria.p3.xy());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** get all triangle-edge-points (x,y,z) within the obstacle */
|
||||
std::vector<Point3> getPoints3D() const {
|
||||
std::vector<Point3> res;
|
||||
for (const Triangle3& tria : triangles) {
|
||||
res.push_back(tria.p1);
|
||||
res.push_back(tria.p2);
|
||||
res.push_back(tria.p3);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user