summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-02-13 14:52:03 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2021-02-13 14:52:03 +0000
commitd2b167f2d1ca15e42a177b65cdf34f35592452f7 (patch)
treeacdd75da65e879412934fb024274a6849b823439
parentFlip texture images to match OpenGL expectations (diff)
downloadilt-d2b167f2d1ca15e42a177b65cdf34f35592452f7.tar.bz2
ilt-d2b167f2d1ca15e42a177b65cdf34f35592452f7.tar.xz
ilt-d2b167f2d1ca15e42a177b65cdf34f35592452f7.zip
New .obj parser, packer, mesher
-rw-r--r--Jamroot.jam1
-rw-r--r--gfx/models/mesh.cpp70
-rw-r--r--gfx/models/mesh.h17
-rw-r--r--gfx/models/obj.h36
-rw-r--r--gfx/models/obj.ll121
-rw-r--r--gfx/models/obj_loader.cpp429
-rw-r--r--gfx/models/obj_loader.h53
7 files changed, 208 insertions, 519 deletions
diff --git a/Jamroot.jam b/Jamroot.jam
index 4e2fefc..e569a31 100644
--- a/Jamroot.jam
+++ b/Jamroot.jam
@@ -18,6 +18,7 @@ project : requirements
<variant>release:<lto>on
<toolset>tidy:<exclude>gfx/gl/shaders/fs-basicShader.h
<toolset>tidy:<exclude>gfx/gl/shaders/vs-basicShader.h
+ <toolset>tidy:<exclude>gfx/models/obj.cpp
<toolset>tidy:<checkxx>boost-*
<toolset>tidy:<checkxx>bugprone-*
<toolset>tidy:<checkxx>clang-*
diff --git a/gfx/models/mesh.cpp b/gfx/models/mesh.cpp
index 4a3d9d4..25a4b58 100644
--- a/gfx/models/mesh.cpp
+++ b/gfx/models/mesh.cpp
@@ -1,41 +1,19 @@
#include "mesh.h"
-#include "obj_loader.h"
+#include "obj.h"
#include "vertex.hpp"
-#include <memory>
+#include <algorithm>
+#include <glm/glm.hpp>
+#include <iterator>
+#include <resource.h>
#include <vector>
-Mesh::Mesh(const std::string & fileName) : Mesh(OBJModel(fileName).ToIndexedModel()) { }
+Mesh::Mesh(const std::filesystem::path & fileName) : Mesh(ObjParser {Resource::mapPath(fileName)}) { }
-Mesh::Mesh(const IndexedModel & model) :
- m_vertexArrayObject {}, m_vertexArrayBuffers {}, m_numIndices {model.indices.size()}, mode {GL_TRIANGLES}
-{
- glGenVertexArrays(1, &m_vertexArrayObject);
- glBindVertexArray(m_vertexArrayObject);
-
- glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers.data());
-
- glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
- glBufferData(
- GL_ARRAY_BUFFER, sizeof(model.positions[0]) * model.positions.size(), &model.positions[0], GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
-
- glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]);
- glBufferData(
- GL_ARRAY_BUFFER, sizeof(model.texCoords[0]) * model.texCoords.size(), &model.texCoords[0], GL_STATIC_DRAW);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+Mesh::Mesh(const ObjParser & obj) : Mesh(packObjParser(obj), GL_TRIANGLES) { }
- glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[NORMAL_VB]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(model.normals[0]) * model.normals.size(), &model.normals[0], GL_STATIC_DRAW);
- glEnableVertexAttribArray(2);
- glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vertexArrayBuffers[INDEX_VB]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(model.indices[0]) * model.indices.size(), &model.indices[0],
- GL_STATIC_DRAW);
-
- glBindVertexArray(0);
+Mesh::Mesh(std::pair<std::vector<Vertex>, std::vector<unsigned int>> && vandi, GLenum m) :
+ Mesh(vandi.first, vandi.second, m)
+{
}
Mesh::Mesh(std::span<Vertex> vertices, std::span<unsigned int> indices, GLenum m) :
@@ -64,6 +42,34 @@ Mesh::Mesh(std::span<Vertex> vertices, std::span<unsigned int> indices, GLenum m
glBindVertexArray(0);
}
+Mesh::Data
+Mesh::packObjParser(const ObjParser & obj)
+{
+ std::vector<Vertex> vertices;
+ std::vector<ObjParser::FaceElement> vertexOrder;
+ std::vector<unsigned int> indices;
+ std::for_each(obj.faces.begin(), obj.faces.end(), [&](const ObjParser::Face & face) {
+ for (auto idx = 2U; idx < face.size(); idx += 1) {
+ auto f = [&](auto idx) {
+ const auto & fe {face[idx]};
+ if (const auto existing = std::find(vertexOrder.begin(), vertexOrder.end(), fe);
+ existing != vertexOrder.end()) {
+ indices.push_back(std::distance(vertexOrder.begin(), existing));
+ }
+ else {
+ indices.push_back(vertices.size());
+ vertices.emplace_back(obj.vertices[fe.x - 1], obj.texCoords[fe.y - 1], -obj.normals[fe.z - 1]);
+ vertexOrder.emplace_back(fe);
+ }
+ };
+ f(0);
+ f(idx);
+ f(idx - 1);
+ }
+ });
+ return std::make_pair(vertices, indices);
+}
+
Mesh::~Mesh()
{
glDeleteBuffers(NUM_BUFFERS, m_vertexArrayBuffers.data());
diff --git a/gfx/models/mesh.h b/gfx/models/mesh.h
index ebd300b..4982145 100644
--- a/gfx/models/mesh.h
+++ b/gfx/models/mesh.h
@@ -4,19 +4,22 @@
#include <GL/glew.h>
#include <array>
#include <cstddef>
+#include <filesystem>
+#include <gfx/models/vertex.hpp>
#include <span>
#include <special_members.hpp>
-#include <string>
+#include <utility>
+#include <vector>
-class IndexedModel;
-class Vertex;
+class ObjParser;
enum MeshBufferPositions { POSITION_VB, TEXCOORD_VB, NORMAL_VB, INDEX_VB };
class Mesh {
public:
- explicit Mesh(const std::string & fileName);
- explicit Mesh(const IndexedModel & model);
+ using Data = std::pair<std::vector<Vertex>, std::vector<unsigned int>>;
+ explicit Mesh(const std::filesystem::path & fileName);
+ explicit Mesh(const ObjParser & obj);
Mesh(std::span<Vertex> vertices, std::span<unsigned int> indices, GLenum = GL_TRIANGLES);
virtual ~Mesh();
@@ -26,6 +29,10 @@ public:
void Draw() const;
private:
+ explicit Mesh(Data && vandi, GLenum = GL_TRIANGLES);
+
+ static Data packObjParser(const ObjParser &);
+
static constexpr unsigned int NUM_BUFFERS {4};
GLuint m_vertexArrayObject;
diff --git a/gfx/models/obj.h b/gfx/models/obj.h
new file mode 100644
index 0000000..96c5e94
--- /dev/null
+++ b/gfx/models/obj.h
@@ -0,0 +1,36 @@
+#ifndef OBJ_H
+#define OBJ_H
+
+#ifndef yyFlexLexer
+# define yyFlexLexer objbaseFlexLexer
+# include <FlexLexer.h>
+#endif
+#include <filesystem>
+#include <fstream>
+#include <glm/glm.hpp>
+#include <memory>
+#include <vector>
+
+class ObjParser : yyFlexLexer {
+public:
+ explicit ObjParser(const std::filesystem::path & fileName) : ObjParser {std::make_unique<std::ifstream>(fileName)}
+ {
+ }
+
+ explicit ObjParser(std::unique_ptr<std::istream> in) : yyFlexLexer(in.get())
+ {
+ ObjParser::yylex();
+ }
+
+ int yylex() override;
+
+ std::vector<glm::vec4> vertices;
+ std::vector<glm::vec3> texCoords;
+ std::vector<glm::vec3> normals;
+ using FaceElement = glm::vec<3, int>;
+ using Face = std::vector<FaceElement>;
+ std::vector<Face> faces;
+ glm::length_t axis {0};
+};
+
+#endif
diff --git a/gfx/models/obj.ll b/gfx/models/obj.ll
new file mode 100644
index 0000000..9329a5a
--- /dev/null
+++ b/gfx/models/obj.ll
@@ -0,0 +1,121 @@
+%option batch
+%option c++
+%option noyywrap
+%option 8bit
+%option stack
+%option yyclass="ObjParser"
+%option prefix="objbase"
+
+%{
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#if __clang__
+#pragma GCC diagnostic ignored "-Wnull-conversion"
+#endif
+#include <gfx/models/obj.h>
+#include <glm/glm.hpp>
+#include <memory>
+#include <string>
+#include <vector>
+class objbaseFlexLexer;
+%}
+
+comment #.*
+float -?[0-9.]+
+index -?[0-9]+
+linestring [^\r\n]*
+truthy (1|on)
+falsey (0|off)
+
+%x FACE
+%x MTLLIB
+%x OBJECT
+%x SMOOTH
+%x USEMTL
+%x VERTEX
+%x NORMAL
+%x TEXCOORD
+
+%%
+
+<INITIAL>{comment} {
+ // fprintf(stderr, "COMMENT %s\n", YYText());
+}
+<INITIAL>"f " {
+ BEGIN(FACE);
+ faces.emplace_back();
+ faces.back().emplace_back();
+ axis = 0;
+}
+<INITIAL>"mtllib " {
+ BEGIN(MTLLIB);
+}
+<INITIAL>"o " {
+ BEGIN(OBJECT);
+}
+<INITIAL>"s " {
+ BEGIN(SMOOTH);
+}
+<INITIAL>"usemtl " {
+ BEGIN(USEMTL);
+}
+<INITIAL>"v " {
+ BEGIN(VERTEX);
+ vertices.emplace_back(0, 0, 0, 1);
+ axis = 0;
+}
+<INITIAL>"vn " {
+ BEGIN(NORMAL);
+ normals.emplace_back(0, 0, 0);
+ axis = 0;
+}
+<INITIAL>"vt " {
+ BEGIN(TEXCOORD);
+ texCoords.emplace_back(0, 1, 1);
+ axis = 0;
+}
+<USEMTL>{linestring} {
+ // fprintf(stderr, "USEMTL <%s>\n", YYText());
+}
+<MTLLIB>{linestring} {
+ // fprintf(stderr, "MTLLIB <%s>\n", YYText());
+}
+<OBJECT>{linestring} {
+ // fprintf(stderr, "OBJECT <%s>\n", YYText());
+}
+<SMOOTH>{truthy} {
+ // fprintf(stderr, "Set smooth\n");
+}
+<SMOOTH>{falsey} {
+ // fprintf(stderr, "Set flat\n");
+}
+<VERTEX>{float} {
+ vertices.back()[axis++] = std::stof(YYText());
+}
+<NORMAL>{float} {
+ normals.back()[axis++] = std::stof(YYText());
+}
+<TEXCOORD>{float} {
+ texCoords.back()[axis++] = std::stof(YYText());
+}
+<FACE>{index} {
+ faces.back().back()[axis] = std::stoi(YYText());
+}
+<FACE>\/ {
+ axis++;
+}
+<FACE>[ \t] {
+ faces.back().emplace_back();
+ axis = 0;
+}
+
+<*>[ \t] {
+}
+<*>[\r\n\f] {
+ BEGIN(INITIAL);
+}
+
+%%
+
+// Make iwyu think unistd.h is required
+[[maybe_unused]]static auto x=getpid;
diff --git a/gfx/models/obj_loader.cpp b/gfx/models/obj_loader.cpp
deleted file mode 100644
index 75ab251..0000000
--- a/gfx/models/obj_loader.cpp
+++ /dev/null
@@ -1,429 +0,0 @@
-#include "obj_loader.h"
-#include <algorithm>
-#include <fstream>
-#include <map>
-#include <memory>
-#include <resource.h>
-#include <stdexcept>
-#include <utility>
-
-static bool CompareOBJIndexPtr(const OBJIndex * a, const OBJIndex * b);
-static inline unsigned int FindNextChar(unsigned int start, const char * str, unsigned int length, char token);
-static inline unsigned int ParseOBJIndexValue(const std::string & token, unsigned int start, unsigned int end);
-static inline float ParseOBJFloatValue(const std::string & token, unsigned int start, unsigned int end);
-static inline std::vector<std::string> SplitString(const std::string & s, char delim);
-
-OBJModel::OBJModel(const std::filesystem::path & fileName)
-{
- hasUVs = false;
- hasNormals = false;
- std::ifstream file;
- file.open(Resource::mapPath(fileName).c_str());
-
- std::string line;
- if (file.is_open()) {
- while (file.good()) {
- getline(file, line);
-
- unsigned int lineLength = line.length();
-
- if (lineLength < 2) {
- continue;
- }
-
- const char * lineCStr = line.c_str();
-
- switch (lineCStr[0]) {
- case 'v':
- switch (lineCStr[1]) {
- case 't':
- this->uvs.push_back(ParseOBJVec2(line));
- break;
- case 'n':
- this->normals.push_back(ParseOBJVec3(line));
- break;
- case ' ':
- case '\t':
- this->vertices.push_back(ParseOBJVec3(line));
- }
- break;
- case 'f':
- CreateOBJFace(line);
- break;
- default:
- break;
- };
- }
- }
- else {
- throw std::runtime_error {"Unable to load mesh: " + fileName.string()};
- }
-}
-
-void
-IndexedModel::CalcNormals()
-{
- for (unsigned int i = 0; i < indices.size(); i += 3) {
- int i0 = indices[i];
- int i1 = indices[i + 1];
- int i2 = indices[i + 2];
-
- glm::vec3 v1 = positions[i1] - positions[i0];
- glm::vec3 v2 = positions[i2] - positions[i0];
-
- glm::vec3 normal = glm::normalize(glm::cross(v1, v2));
-
- normals[i0] += normal;
- normals[i1] += normal;
- normals[i2] += normal;
- }
-
- for (unsigned int i = 0; i < positions.size(); i++) {
- normals[i] = glm::normalize(normals[i]);
- }
-}
-
-IndexedModel
-OBJModel::ToIndexedModel()
-{
- IndexedModel result;
- IndexedModel normalModel;
-
- unsigned int numIndices = OBJIndices.size();
-
- std::vector<OBJIndex *> indexLookup;
-
- for (unsigned int i = 0; i < numIndices; i++) {
- indexLookup.push_back(&OBJIndices[i]);
- }
-
- std::sort(indexLookup.begin(), indexLookup.end(), CompareOBJIndexPtr);
-
- std::map<OBJIndex, unsigned int> normalModelIndexMap;
- std::map<unsigned int, unsigned int> indexMap;
-
- for (unsigned int i = 0; i < numIndices; i++) {
- OBJIndex * currentIndex = &OBJIndices[i];
-
- glm::vec3 currentPosition = vertices[currentIndex->vertexIndex];
- glm::vec2 currentTexCoord;
- glm::vec3 currentNormal;
-
- if (hasUVs) {
- currentTexCoord = uvs[currentIndex->uvIndex];
- }
- else {
- currentTexCoord = glm::vec2(0, 0);
- }
-
- if (hasNormals) {
- currentNormal = normals[currentIndex->normalIndex];
- }
- else {
- currentNormal = glm::vec3(0, 0, 0);
- }
-
- unsigned int normalModelIndex;
- unsigned int resultModelIndex;
-
- // Create model to properly generate normals on
- const auto it = normalModelIndexMap.find(*currentIndex);
- if (it == normalModelIndexMap.end()) {
- normalModelIndex = normalModel.positions.size();
-
- normalModelIndexMap.insert(std::pair<OBJIndex, unsigned int>(*currentIndex, normalModelIndex));
- normalModel.positions.push_back(currentPosition);
- normalModel.texCoords.push_back(currentTexCoord);
- normalModel.normals.push_back(currentNormal);
- }
- else {
- normalModelIndex = it->second;
- }
-
- // Create model which properly separates texture coordinates
- unsigned int previousVertexLocation = FindLastVertexIndex(indexLookup, currentIndex, result);
-
- if (previousVertexLocation == (unsigned int)-1) {
- resultModelIndex = result.positions.size();
-
- result.positions.push_back(currentPosition);
- result.texCoords.push_back(currentTexCoord);
- result.normals.push_back(currentNormal);
- }
- else {
- resultModelIndex = previousVertexLocation;
- }
-
- normalModel.indices.push_back(normalModelIndex);
- result.indices.push_back(resultModelIndex);
- indexMap.insert(std::pair<unsigned int, unsigned int>(resultModelIndex, normalModelIndex));
- }
-
- if (!hasNormals) {
- normalModel.CalcNormals();
-
- for (unsigned int i = 0; i < result.positions.size(); i++) {
- result.normals[i] = normalModel.normals[indexMap[i]];
- }
- }
-
- return result;
-};
-
-unsigned int
-OBJModel::FindLastVertexIndex(
- const std::vector<OBJIndex *> & indexLookup, const OBJIndex * currentIndex, const IndexedModel & result)
-{
- unsigned int start = 0;
- unsigned int end = indexLookup.size();
- unsigned int current = (end - start) / 2 + start;
- unsigned int previous = start;
-
- while (current != previous) {
- OBJIndex * testIndex = indexLookup[current];
-
- if (testIndex->vertexIndex == currentIndex->vertexIndex) {
- unsigned int countStart = current;
-
- for (unsigned int i = 0; i < current; i++) {
- OBJIndex * possibleIndex = indexLookup[current - i];
-
- if (possibleIndex == currentIndex) {
- continue;
- }
-
- if (possibleIndex->vertexIndex != currentIndex->vertexIndex) {
- break;
- }
-
- countStart--;
- }
-
- for (unsigned int i = countStart; i < indexLookup.size() - countStart; i++) {
- OBJIndex * possibleIndex = indexLookup[current + i];
-
- if (possibleIndex == currentIndex) {
- continue;
- }
-
- if (possibleIndex->vertexIndex != currentIndex->vertexIndex) {
- break;
- }
- else if ((!hasUVs || possibleIndex->uvIndex == currentIndex->uvIndex)
- && (!hasNormals || possibleIndex->normalIndex == currentIndex->normalIndex)) {
- glm::vec3 currentPosition = vertices[currentIndex->vertexIndex];
- glm::vec2 currentTexCoord;
- glm::vec3 currentNormal;
-
- if (hasUVs) {
- currentTexCoord = uvs[currentIndex->uvIndex];
- }
- else {
- currentTexCoord = glm::vec2(0, 0);
- }
-
- if (hasNormals) {
- currentNormal = normals[currentIndex->normalIndex];
- }
- else {
- currentNormal = glm::vec3(0, 0, 0);
- }
-
- for (unsigned int j = 0; j < result.positions.size(); j++) {
- if (currentPosition == result.positions[j]
- && ((!hasUVs || currentTexCoord == result.texCoords[j])
- && (!hasNormals || currentNormal == result.normals[j]))) {
- return j;
- }
- }
- }
- }
-
- return -1;
- }
- else {
- if (testIndex->vertexIndex < currentIndex->vertexIndex) {
- start = current;
- }
- else {
- end = current;
- }
- }
-
- previous = current;
- current = (end - start) / 2 + start;
- }
-
- return -1;
-}
-
-void
-OBJModel::CreateOBJFace(const std::string & line)
-{
- std::vector<std::string> tokens = SplitString(line, ' ');
-
- this->OBJIndices.push_back(ParseOBJIndex(tokens[1], &this->hasUVs, &this->hasNormals));
- this->OBJIndices.push_back(ParseOBJIndex(tokens[2], &this->hasUVs, &this->hasNormals));
- this->OBJIndices.push_back(ParseOBJIndex(tokens[3], &this->hasUVs, &this->hasNormals));
-
- if ((int)tokens.size() > 4) {
- this->OBJIndices.push_back(ParseOBJIndex(tokens[1], &this->hasUVs, &this->hasNormals));
- this->OBJIndices.push_back(ParseOBJIndex(tokens[3], &this->hasUVs, &this->hasNormals));
- this->OBJIndices.push_back(ParseOBJIndex(tokens[4], &this->hasUVs, &this->hasNormals));
- }
-}
-
-OBJIndex
-OBJModel::ParseOBJIndex(const std::string & token, bool * hasUVs, bool * hasNormals)
-{
- unsigned int tokenLength = token.length();
- const char * tokenString = token.c_str();
-
- unsigned int vertIndexStart = 0;
- unsigned int vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, '/');
-
- OBJIndex result {
- .vertexIndex = ParseOBJIndexValue(token, vertIndexStart, vertIndexEnd),
- .uvIndex = 0,
- .normalIndex = 0,
- };
-
- if (vertIndexEnd >= tokenLength) {
- return result;
- }
-
- vertIndexStart = vertIndexEnd + 1;
- vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, '/');
-
- result.uvIndex = ParseOBJIndexValue(token, vertIndexStart, vertIndexEnd);
- *hasUVs = true;
-
- if (vertIndexEnd >= tokenLength) {
- return result;
- }
-
- vertIndexStart = vertIndexEnd + 1;
- vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, '/');
-
- result.normalIndex = ParseOBJIndexValue(token, vertIndexStart, vertIndexEnd);
- *hasNormals = true;
-
- return result;
-}
-
-glm::vec3
-OBJModel::ParseOBJVec3(const std::string & line)
-{
- unsigned int tokenLength = line.length();
- const char * tokenString = line.c_str();
-
- unsigned int vertIndexStart = 2;
-
- while (vertIndexStart < tokenLength) {
- if (tokenString[vertIndexStart] != ' ') {
- break;
- }
- vertIndexStart++;
- }
-
- unsigned int vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, ' ');
-
- float x = ParseOBJFloatValue(line, vertIndexStart, vertIndexEnd);
-
- vertIndexStart = vertIndexEnd + 1;
- vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, ' ');
-
- float y = ParseOBJFloatValue(line, vertIndexStart, vertIndexEnd);
-
- vertIndexStart = vertIndexEnd + 1;
- vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, ' ');
-
- float z = ParseOBJFloatValue(line, vertIndexStart, vertIndexEnd);
-
- return glm::vec3(x, y, z);
-}
-
-glm::vec2
-OBJModel::ParseOBJVec2(const std::string & line)
-{
- unsigned int tokenLength = line.length();
- const char * tokenString = line.c_str();
-
- unsigned int vertIndexStart = 3;
-
- while (vertIndexStart < tokenLength) {
- if (tokenString[vertIndexStart] != ' ') {
- break;
- }
- vertIndexStart++;
- }
-
- unsigned int vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, ' ');
-
- float x = ParseOBJFloatValue(line, vertIndexStart, vertIndexEnd);
-
- vertIndexStart = vertIndexEnd + 1;
- vertIndexEnd = FindNextChar(vertIndexStart, tokenString, tokenLength, ' ');
-
- float y = ParseOBJFloatValue(line, vertIndexStart, vertIndexEnd);
-
- return glm::vec2(x, y);
-}
-
-static bool
-CompareOBJIndexPtr(const OBJIndex * a, const OBJIndex * b)
-{
- return a->vertexIndex < b->vertexIndex;
-}
-
-static inline unsigned int
-FindNextChar(unsigned int start, const char * str, unsigned int length, char token)
-{
- unsigned int result = start;
- while (result < length) {
- result++;
- if (str[result] == token) {
- break;
- }
- }
-
- return result;
-}
-
-static inline unsigned int
-ParseOBJIndexValue(const std::string & token, unsigned int start, unsigned int end)
-{
- return std::stoul(token.substr(start, end - start)) - 1;
-}
-
-static inline float
-ParseOBJFloatValue(const std::string & token, unsigned int start, unsigned int end)
-{
- return std::stof(token.substr(start, end - start));
-}
-
-static inline std::vector<std::string>
-SplitString(const std::string & s, char delim)
-{
- std::vector<std::string> elems;
-
- const char * cstr = s.c_str();
- unsigned int strLength = s.length();
- unsigned int start = 0;
- unsigned int end = 0;
-
- while (end <= strLength) {
- while (end <= strLength) {
- if (cstr[end] == delim) {
- break;
- }
- end++;
- }
-
- elems.push_back(s.substr(start, end - start));
- start = end + 1;
- end = start;
- }
-
- return elems;
-}
diff --git a/gfx/models/obj_loader.h b/gfx/models/obj_loader.h
deleted file mode 100644
index 2fe3d35..0000000
--- a/gfx/models/obj_loader.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef OBJ_LOADER_H_INCLUDED
-#define OBJ_LOADER_H_INCLUDED
-
-#include <filesystem>
-#include <glm/glm.hpp>
-#include <string>
-#include <vector>
-
-struct OBJIndex {
- unsigned int vertexIndex;
- unsigned int uvIndex;
- unsigned int normalIndex;
-
- bool
- operator<(const OBJIndex & r) const
- {
- return vertexIndex < r.vertexIndex;
- }
-};
-
-class IndexedModel {
-public:
- std::vector<glm::vec3> positions;
- std::vector<glm::vec2> texCoords;
- std::vector<glm::vec3> normals;
- std::vector<unsigned int> indices;
-
- void CalcNormals();
-};
-
-class OBJModel {
-public:
- std::vector<OBJIndex> OBJIndices;
- std::vector<glm::vec3> vertices;
- std::vector<glm::vec2> uvs;
- std::vector<glm::vec3> normals;
- bool hasUVs;
- bool hasNormals;
-
- explicit OBJModel(const std::filesystem::path & fileName);
-
- IndexedModel ToIndexedModel();
-
-private:
- unsigned int FindLastVertexIndex(
- const std::vector<OBJIndex *> & indexLookup, const OBJIndex * currentIndex, const IndexedModel & result);
- void CreateOBJFace(const std::string & line);
- static glm::vec2 ParseOBJVec2(const std::string & line);
- static glm::vec3 ParseOBJVec3(const std::string & line);
- static OBJIndex ParseOBJIndex(const std::string & token, bool * hasUVs, bool * hasNormals);
-};
-
-#endif // OBJ_LOADER_H_INCLUDED