include objects within navmesh calculation include objects within 3d mesh generation minor changes/fixes
170 lines
4.0 KiB
C++
170 lines
4.0 KiB
C++
#ifndef OBJREADER_H
|
|
#define OBJREADER_H
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <fstream>
|
|
#include "../../../geo/Point2.h"
|
|
#include "../../../geo/Point3.h"
|
|
|
|
/**
|
|
* prase .obj files
|
|
*/
|
|
class OBJReader {
|
|
|
|
public:
|
|
|
|
|
|
/** group vertex+normal+texture */
|
|
struct VNT {
|
|
int idxVertex;
|
|
int idxNormal;
|
|
int idxTexture;
|
|
Point3 vertex;
|
|
Point3 normal;
|
|
Point2 texture;
|
|
};
|
|
|
|
/** one triangle */
|
|
struct Face {
|
|
VNT vnt[3];
|
|
Face(VNT v1, VNT v2, VNT v3) : vnt({v1,v2,v3}) {;}
|
|
};
|
|
|
|
/** internal data */
|
|
struct Data {
|
|
std::vector<Point3> vertices;
|
|
std::vector<Point2> texCoords;
|
|
std::vector<Point3> normals;
|
|
std::vector<Face> faces;
|
|
} data;
|
|
|
|
|
|
public:
|
|
|
|
/** ctor. use readXYZ() */
|
|
OBJReader() {
|
|
;
|
|
}
|
|
|
|
/** 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 parsed data */
|
|
const Data& getData() const {return data;}
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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(const std::string& line) {
|
|
|
|
if (line.length() < 2) {return;}
|
|
|
|
const std::vector<std::string> tokens = 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);}
|
|
|
|
}
|
|
|
|
/** parse one vertex from the tokenizer */
|
|
void parseVertex(const std::vector<std::string>& t) {
|
|
const float x = std::stof(t[1]);
|
|
const float y = std::stof(t[2]);
|
|
const float z = std::stof(t[3]);
|
|
data.vertices.push_back(Point3(x,y,z));
|
|
}
|
|
|
|
/** parse one texture-coordinate from the tokenizer */
|
|
void parseTexCoord(const std::vector<std::string>& t) {
|
|
const float u = std::stof(t[1]);
|
|
const float v = std::stof(t[2]);
|
|
data.texCoords.push_back(Point2(u, -v));
|
|
}
|
|
|
|
/** parse one normal from the tokenizer */
|
|
void parseNormal(const std::vector<std::string>& t) {
|
|
const float x = std::stof(t[1]);
|
|
const float y = std::stof(t[2]);
|
|
const float z = std::stof(t[3]);
|
|
data.normals.push_back(Point3(x,y,z));
|
|
}
|
|
|
|
/** parse one face from the tokenizer */
|
|
void parseFace(const std::vector<std::string>& t) {
|
|
|
|
std::vector<VNT> indices;
|
|
|
|
int numVertices = 0;
|
|
for (size_t i = 1; i < t.size(); ++i) {
|
|
|
|
// one V/T/N
|
|
const std::string entry = t[i];
|
|
const std::vector<std::string> vtn = split(entry, '/');
|
|
|
|
++numVertices;
|
|
const std::string v = vtn[0];
|
|
//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);
|
|
|
|
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];}
|
|
|
|
indices.push_back(vnt);
|
|
|
|
}
|
|
|
|
// this will both, create normal triangles and triangulate polygons
|
|
// 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);
|
|
}
|
|
|
|
// sanity check
|
|
if (numVertices != 3) {throw "this face is not a triangle!";}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif // OBJREADER_H
|