206 lines
8.4 KiB
C++

//
// Created by karl on 12.01.20.
//
#ifndef ECSGAME_OBJMESH_H
#define ECSGAME_OBJMESH_H
#include "../../Util/OBJ_Loader.h"
#include "Mesh.h"
struct ObjMesh : public Mesh {
struct Settings {
Settings() = default;
Settings(float minDistanceForRender, float maxDistanceForRender, float diffuse,
float specular, bool colliding)
: minDistanceForRender(minDistanceForRender),
maxDistanceForRender(maxDistanceForRender), colliding(colliding) {}
float minDistanceForRender = 0.0;
float maxDistanceForRender = 1000.0;
bool colliding = true;
};
explicit ObjMesh(const std::string &path, const Settings &settings)
: Mesh(getVerticesFromFile(path), getIndicesFromFile(path)),
minDistance(settings.minDistanceForRender), maxDistance(settings.maxDistanceForRender),
colliding(settings.colliding) {}
float minDistance;
float maxDistance;
bool colliding;
private:
static std::vector<float> getVerticesFromFile(const std::string &path) {
objl::Loader loader;
bool loadout = loader.LoadFile(path);
if (loadout) {
// TODO: Currently only the first mesh is used
objl::Mesh curMesh = loader.LoadedMeshes[0];
std::vector<float> vertexData = std::vector<float>();
auto tangents = getTangentsFromVertices(curMesh.Vertices, getIndicesFromFile(path));
for (int i = 0; i <= curMesh.Vertices.size(); i++) {
auto vertex = curMesh.Vertices[i];
auto tangent = tangents.first[i];
auto bitangent = tangents.second[i];
vertexData.emplace_back(vertex.Position.X);
vertexData.emplace_back(vertex.Position.Y);
vertexData.emplace_back(vertex.Position.Z);
vertexData.emplace_back(vertex.Normal.X);
vertexData.emplace_back(vertex.Normal.Y);
vertexData.emplace_back(vertex.Normal.Z);
vertexData.emplace_back(vertex.TextureCoordinate.X);
vertexData.emplace_back(vertex.TextureCoordinate.Y);
vertexData.emplace_back(tangent.x);
vertexData.emplace_back(tangent.y);
vertexData.emplace_back(tangent.z);
vertexData.emplace_back(bitangent.x);
vertexData.emplace_back(bitangent.y);
vertexData.emplace_back(bitangent.z);
}
return vertexData;
} else {
// Output Error
std::cout
<< "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
}
}
static std::pair<std::vector<glm::vec3>, std::vector<glm::vec3>>
getTangentsFromVertices(const std::vector<objl::Vertex> &vertices,
const std::vector<unsigned int> indices) {
// These vectors hold tangents and bitangents in the same way in which the vertices vectors
// holds vertices: Their index in the vector corresponds to indices in the indices vector.
std::vector<glm::vec3> tangents(vertices.size());
std::vector<glm::vec3> bitangents(vertices.size());
// Iterate over all triangles
for (uint index = 0; index < indices.size(); index += 3) {
// Index in vertex buffer
uint i0 = indices[index];
uint i1 = indices[index + 1];
uint i2 = indices[index + 2];
// Inputs
glm::vec3 vertex0 = glm::vec3(vertices[i0].Position.X, vertices[i0].Position.Y,
vertices[i0].Position.Z);
glm::vec3 vertex1 = glm::vec3(vertices[i1].Position.X, vertices[i1].Position.Y,
vertices[i1].Position.Z);
glm::vec3 vertex2 = glm::vec3(vertices[i2].Position.X, vertices[i2].Position.Y,
vertices[i2].Position.Z);
glm::vec2 uv0 =
glm::vec2(vertices[i0].TextureCoordinate.X, vertices[i0].TextureCoordinate.Y);
glm::vec2 uv1 =
glm::vec2(vertices[i1].TextureCoordinate.X, vertices[i1].TextureCoordinate.Y);
glm::vec2 uv2 =
glm::vec2(vertices[i2].TextureCoordinate.X, vertices[i2].TextureCoordinate.Y);
glm::vec3 normal0 =
glm::vec3(vertices[i0].Normal.X, vertices[i0].Normal.Y, vertices[i0].Normal.Z);
glm::vec3 normal1 =
glm::vec3(vertices[i1].Normal.X, vertices[i1].Normal.Y, vertices[i1].Normal.Z);
glm::vec3 normal2 =
glm::vec3(vertices[i2].Normal.X, vertices[i2].Normal.Y, vertices[i2].Normal.Z);
// Edges of the triangle : position delta
glm::vec3 deltaPos1 = vertex1 - vertex0;
glm::vec3 deltaPos2 = vertex2 - vertex0;
// UV delta
glm::vec2 deltaUV1 = uv1 - uv0;
glm::vec2 deltaUV2 = uv2 - uv0;
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
glm::vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
glm::vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
// Add the tangent and bitangent to the current value in the array.
// This is done to get an average in the end.
tangents[i0] += tangent;
tangents[i1] += tangent;
tangents[i2] += tangent;
bitangents[i0] += bitangent;
bitangents[i1] += bitangent;
bitangents[i2] += bitangent;
}
return std::pair<std::vector<glm::vec3>, std::vector<glm::vec3>>(tangents, bitangents);
}
static std::vector<unsigned int> getIndicesFromFile(const std::string &path) {
objl::Loader loader;
bool loadout = loader.LoadFile(path);
if (loadout) {
// TODO: Currently only the first mesh is used
objl::Mesh curMesh = loader.LoadedMeshes[0];
std::vector<unsigned int> indices = std::vector<unsigned int>();
// Emplace indices into the float vector
for (int j = 0; j < curMesh.Indices.size(); j++) {
indices.emplace_back(curMesh.Indices[j]);
}
return indices;
} else {
// Output Error
std::cout
<< "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
}
}
// TODO: Only prints at the moment
static std::vector<float> getMaterialFromFile(const std::string &path) {
objl::Loader loader;
bool loadout = loader.LoadFile(path);
if (loadout) {
// TODO: Currently only the first mesh is used
objl::Mesh curMesh = loader.LoadedMeshes[0];
std::vector<float> vertexData = std::vector<float>();
// Print Material
std::cout << "Material: " << curMesh.MeshMaterial.name << "\n";
std::cout << "Ambient Color: " << curMesh.MeshMaterial.Ka.X << ", "
<< curMesh.MeshMaterial.Ka.Y << ", " << curMesh.MeshMaterial.Ka.Z << "\n";
std::cout << "Diffuse Color: " << curMesh.MeshMaterial.Kd.X << ", "
<< curMesh.MeshMaterial.Kd.Y << ", " << curMesh.MeshMaterial.Kd.Z << "\n";
std::cout << "Specular Color: " << curMesh.MeshMaterial.Ks.X << ", "
<< curMesh.MeshMaterial.Ks.Y << ", " << curMesh.MeshMaterial.Ks.Z << "\n";
std::cout << "Specular Exponent: " << curMesh.MeshMaterial.Ns << "\n";
std::cout << "Optical Density: " << curMesh.MeshMaterial.Ni << "\n";
std::cout << "Dissolve: " << curMesh.MeshMaterial.d << "\n";
std::cout << "Illumination: " << curMesh.MeshMaterial.illum << "\n";
std::cout << "Ambient Texture Map: " << curMesh.MeshMaterial.map_Ka << "\n";
std::cout << "Diffuse Texture Map: " << curMesh.MeshMaterial.map_Kd << "\n";
std::cout << "Specular Texture Map: " << curMesh.MeshMaterial.map_Ks << "\n";
std::cout << "Alpha Texture Map: " << curMesh.MeshMaterial.map_d << "\n";
std::cout << "Bump Map: " << curMesh.MeshMaterial.map_bump << "\n";
return vertexData;
} else {
// Output Error
std::cout
<< "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
}
}
};
#endif // ECSGAME_OBJMESH_H