diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-02-13 14:52:03 +0000 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-02-13 14:52:03 +0000 | 
| commit | d2b167f2d1ca15e42a177b65cdf34f35592452f7 (patch) | |
| tree | acdd75da65e879412934fb024274a6849b823439 /gfx | |
| parent | Flip texture images to match OpenGL expectations (diff) | |
| download | ilt-d2b167f2d1ca15e42a177b65cdf34f35592452f7.tar.bz2 ilt-d2b167f2d1ca15e42a177b65cdf34f35592452f7.tar.xz ilt-d2b167f2d1ca15e42a177b65cdf34f35592452f7.zip  | |
New .obj parser, packer, mesher
Diffstat (limited to 'gfx')
| -rw-r--r-- | gfx/models/mesh.cpp | 70 | ||||
| -rw-r--r-- | gfx/models/mesh.h | 17 | ||||
| -rw-r--r-- | gfx/models/obj.h | 36 | ||||
| -rw-r--r-- | gfx/models/obj.ll | 121 | ||||
| -rw-r--r-- | gfx/models/obj_loader.cpp | 429 | ||||
| -rw-r--r-- | gfx/models/obj_loader.h | 53 | 
6 files changed, 207 insertions, 519 deletions
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  | 
