Initial commit: Final state of the master project

This commit is contained in:
2017-09-16 09:41:37 +02:00
commit 696180d43b
832 changed files with 169717 additions and 0 deletions

View File

@@ -0,0 +1,335 @@
#include <fstream>
#include "../inc/assimp/Importer.hpp"
#include "../inc/assimp/scene.h"
#include "../inc/assimp/postprocess.h"
#include "../Renderer.h"
#include "ObjLoader.h"
ObjLoader* ObjLoader::mInstance = NULL;
void ObjLoader::Create() {
if (mInstance == NULL)
mInstance = new ObjLoader();
}
void ObjLoader::Destroy() {
if (mInstance != NULL)
delete mInstance;
mInstance = NULL;
}
ObjLoader* ObjLoader::Instance() {
return mInstance;
}
//************************************
// Load OBJ file with ASSIMP library
// Parse to scene, using binary file if possible
//************************************
bool ObjLoader::Load(const char* fileName, Scene &scene) {
mVertexOffset = 0;
mIndexOffset = 0;
mTextureOffset = 0;
mBinaryFileName = "";
// Try to load binary scene, otherwise parse ASSIMP scene
if (!Read(fileName, scene)) {
// Load OBJ with ASSIMP
Assimp::Importer importer;
const aiScene* loadedScene = importer.ReadFile(fileName, aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_FlipUVs | aiProcess_GenSmoothNormals);
if (!loadedScene) {
// If bad allocation, try loading without joining identical vertices
const char* t = importer.GetErrorString();
if (strcmp(t, "bad allocation") == 0)
loadedScene = importer.ReadFile(fileName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenSmoothNormals);
if (!loadedScene)
return false;
}
// Load textures, only uses diffuse texture
auto s1 = std::string(fileName);
auto path = s1.substr(0, s1.find_last_of("\\/")).append("/");
std::vector<std::string> textures;
std::vector<float> reflectivenesses(loadedScene->mNumMaterials);
textures.resize(loadedScene->mNumMaterials, std::string());
for (unsigned m = 0; m < loadedScene->mNumMaterials; ++m) {
const aiMaterial* currentMat = loadedScene->mMaterials[m];
aiString dummy;
aiString* textureFile = &dummy;
aiGetMaterialTexture(currentMat, aiTextureType::aiTextureType_DIFFUSE, 0, textureFile);
if (textureFile->data[0] != '\0') {
textures[m] = std::string(path).append(textureFile->C_Str());
//aiGetMaterialInteger(currentMat, aiMaterialProperty::)
/*textures[m] = Renderer::Load2DTexture();
if (mTextureOffset < 0) mTextureOffset = textures[m];*/
}
float reflectivity = 1.f;
aiGetMaterialFloat(currentMat, AI_MATKEY_OPACITY, &reflectivity);
reflectivity = 1.f - reflectivity;
reflectivenesses[m] = reflectivity;
//printf("%f\n", reflectivity);
}
for (unsigned m = 0; m < loadedScene->mNumMeshes; ++m) {
const aiMesh* currentMesh = loadedScene->mMeshes[m];
size_t currentVertex = scene.vertices.size();
size_t currentIndex = scene.indices.size();
// Fill vertex positions
for (unsigned i = 0; i < currentMesh->mNumVertices; i++) {
aiVector3D pos = currentMesh->mVertices[i];
scene.vertices.push_back(glm::vec3(pos.x, pos.y, pos.z));
}
// Fill vertices texture coordinates
// Assume 1 set of UV coordinates, AssImp supports 8 sets
if (currentMesh->HasTextureCoords(0)) {
// If this mesh has uv coordinates, then the whole scene should have them.
scene.uvs.resize(scene.vertices.size() - currentMesh->mNumVertices);
// Read the uvs
for (unsigned i = 0; i < currentMesh->mNumVertices; i++) {
aiVector3D UVW = currentMesh->mTextureCoords[0][i];
scene.uvs.push_back(glm::vec2(UVW.x, UVW.y));
}
}
// Fill empty spots
if (scene.uvs.size() != 0)
scene.uvs.resize(scene.vertices.size(), glm::vec2(0));
// Fill vertices normals
if (currentMesh->HasNormals()) {
for (unsigned i = 0; i < currentMesh->mNumVertices; i++) {
aiVector3D n = currentMesh->mNormals[i];
scene.normals.push_back(glm::vec3(n.x, n.y, n.z));
}
}
// Fill empty spots
scene.normals.resize(scene.vertices.size(), glm::vec3(0));
// Fill vertex colors (if they are set)
if (currentMesh->HasVertexColors(0))
{
// If this mesh has colored vertices, then the whole scene should have them.
scene.colors.resize(scene.vertices.size() - currentMesh->mNumVertices);
// Read the vertex coordinates
for (unsigned i = 0; i < currentMesh->mNumVertices; i++) {
aiColor4D col = currentMesh->mColors[0][i];
scene.colors.push_back(glm::vec3(col.r, col.g, col.b));
}
}
// If the scene has colors, fill them with the color white for the whole scene
if (scene.colors.size() != 0)
scene.colors.resize(scene.vertices.size(), glm::vec3(1));
// Fill triangle indices
for (unsigned i = 0; i < currentMesh->mNumFaces; i++) {
scene.indices.push_back((unsigned)(currentVertex + currentMesh->mFaces[i].mIndices[0]));
scene.indices.push_back((unsigned)(currentVertex + currentMesh->mFaces[i].mIndices[1]));
scene.indices.push_back((unsigned)(currentVertex + currentMesh->mFaces[i].mIndices[2]));
}
// Save mesh
Mesh mesh;
mesh.offset = (unsigned)currentIndex;
mesh.size = (unsigned)(scene.indices.size() - currentIndex);
mesh.texture = textures[currentMesh->mMaterialIndex];
mesh.hasUVs = currentMesh->HasTextureCoords(0);
mesh.hasVertexColors = currentMesh->HasVertexColors(0);
mesh.reflectivity = reflectivenesses[currentMesh->mMaterialIndex];
scene.meshes.push_back(mesh);
if (mVertexOffset <= 0) mVertexOffset = currentVertex;
if (mIndexOffset <= 0) mIndexOffset = currentIndex;
}
if (!Write(fileName, scene))
return false;
textures.clear();
}
// The scene pointer is deleted automatically by importer
return true;
}
ObjLoader::ObjLoader() {
mVertexOffset = 0;
mIndexOffset = 0;
mTextureOffset = 0;
mBinaryFileName = "";
}
ObjLoader::~ObjLoader() {
}
//************************************
// Get binary file name
//************************************
void ObjLoader::GetBinaryFileName(const char* fileName) {
if (mBinaryFileName.empty()) {
mBinaryFileName = fileName;
mBinaryFileName.append(".bin");
}
}
bool ReadFile(std::ifstream& sceneInFile, Scene &scene)
{
try
{
int readVertexOffset, readIndexOffset, readTextureOffset;
sceneInFile.read((char*)&readVertexOffset, sizeof(int));
sceneInFile.read((char*)&readIndexOffset, sizeof(int));
sceneInFile.read((char*)&readTextureOffset, sizeof(int));
unsigned verticesSize, uvsSize, normalsSize, colorsSize, indicesSize, meshesSize;
sceneInFile.read((char*)&verticesSize, sizeof(unsigned));
sceneInFile.read((char*)&uvsSize, sizeof(unsigned));
sceneInFile.read((char*)&normalsSize, sizeof(unsigned));
sceneInFile.read((char*)&colorsSize, sizeof(unsigned));
sceneInFile.read((char*)&indicesSize, sizeof(unsigned));
sceneInFile.read((char*)&meshesSize, sizeof(unsigned));
// Check if the sizes are valid. If they are not, we're probably dealing with an old file
if (meshesSize > verticesSize || (colorsSize != 0 && colorsSize != verticesSize) || normalsSize != verticesSize || (uvsSize != 0 && uvsSize != verticesSize))
return false;
if (!scene.uvs.empty() || uvsSize != 0)
scene.uvs.resize(scene.vertices.size() + verticesSize, glm::vec2(0));
scene.normals.resize(scene.normals.size() + normalsSize);
if (!scene.colors.empty() || colorsSize != 0)
scene.colors.resize(scene.vertices.size() + verticesSize, glm::vec3(1));
scene.indices.resize(scene.indices.size() + indicesSize);
scene.meshes.resize(scene.meshes.size() + meshesSize);
scene.vertices.resize(scene.vertices.size() + verticesSize);
if (verticesSize != 0) sceneInFile.read((char*)&scene.vertices[scene.vertices.size() - verticesSize], sizeof(glm::vec3) * verticesSize);
if (sceneInFile.eof()) return false;
if (uvsSize != 0) sceneInFile.read((char*)&scene.uvs[scene.uvs.size() - uvsSize], sizeof(glm::vec2) * uvsSize);
if (sceneInFile.eof()) return false;
if (normalsSize != 0) sceneInFile.read((char*)&scene.normals[scene.normals.size() - normalsSize], sizeof(glm::vec3) * normalsSize);
if (sceneInFile.eof()) return false;
if (colorsSize != 0) sceneInFile.read((char*)&scene.colors[scene.colors.size() - colorsSize], sizeof(glm::vec3) * colorsSize);
if (sceneInFile.eof()) return false;
if (indicesSize != 0) sceneInFile.read((char*)&scene.indices[scene.indices.size() - indicesSize], sizeof(unsigned) * indicesSize);
if (sceneInFile.eof()) return false;
for (unsigned i = 0; i < meshesSize; i++) {
if (sceneInFile.eof()) return false;
Mesh mesh;
sceneInFile.read((char*)&mesh.offset, sizeof(unsigned));
sceneInFile.read((char*)&mesh.size, sizeof(unsigned));
unsigned int textureSize;
sceneInFile.read((char*)&textureSize, sizeof(unsigned int));
char* texture = new char[textureSize + 1];
sceneInFile.read((char*)&texture[0], textureSize);
texture[textureSize] = '\0';
mesh.texture = std::string(texture);
if (sceneInFile.eof()) return false;
sceneInFile.read((char*)&mesh.hasUVs, sizeof(bool));
if (sceneInFile.eof()) return false;
sceneInFile.read((char*)&mesh.hasVertexColors, sizeof(bool));
sceneInFile.read((char*)&mesh.reflectivity, sizeof(float));
delete[] texture;
scene.meshes[i] = mesh;
}
return true;
}
catch (std::exception& ex)
{
printf("An exception occured while reading the mesh cache file: %s", ex.what());
return false;
}
}
//************************************
// Read scene from binary file
//************************************
bool ObjLoader::Read(const char* fileName, Scene &scene) {
GetBinaryFileName(fileName);
std::ifstream sceneInFile(mBinaryFileName, std::ios::binary);
if (sceneInFile.good()) {
mVertexOffset = (unsigned)scene.vertices.size();
mIndexOffset = (unsigned)scene.indices.size();
unsigned verticesSize = (unsigned)scene.vertices.size();
unsigned uvsSize = (unsigned)scene.uvs.size();
unsigned normalsSize = (unsigned)scene.normals.size();
unsigned colorsSize = (unsigned)scene.colors.size();
unsigned indicesSize = (unsigned)scene.indices.size();
unsigned meshesSize = (unsigned)scene.meshes.size();
bool readSucces = ReadFile(sceneInFile, scene);
if (!readSucces)
{
// Revert the scene if reading failed
scene.vertices.resize(verticesSize); scene.vertices.shrink_to_fit();
scene.uvs.resize(uvsSize); scene.uvs.shrink_to_fit();
scene.normals.resize(normalsSize); scene.normals.shrink_to_fit();
scene.colors.resize(colorsSize); scene.colors.shrink_to_fit();
scene.indices.resize(indicesSize); scene.indices.shrink_to_fit();
scene.meshes.resize(meshesSize); scene.meshes.shrink_to_fit();
}
sceneInFile.close();
return readSucces;
}
return false;
}
//************************************
// Write scene to binary file
//************************************
bool ObjLoader::Write(const char* fileName, Scene &scene) {
GetBinaryFileName(fileName);
std::ofstream sceneOutFile(mBinaryFileName, std::ios::binary);
unsigned verticesSize = (unsigned)scene.vertices.size();
unsigned uvsSize = (unsigned)scene.uvs.size();
unsigned normalsSize = (unsigned)scene.normals.size();
unsigned colorsSize = (unsigned)scene.colors.size();
unsigned indicesSize = (unsigned)scene.indices.size();
unsigned meshesSize = (unsigned)scene.meshes.size();
sceneOutFile.write((char*)&mVertexOffset, sizeof(int));
sceneOutFile.write((char*)&mIndexOffset, sizeof(int));
sceneOutFile.write((char*)&mTextureOffset, sizeof(int));
sceneOutFile.write((char*)&verticesSize, sizeof(unsigned));
sceneOutFile.write((char*)&uvsSize, sizeof(unsigned));
sceneOutFile.write((char*)&normalsSize, sizeof(unsigned));
sceneOutFile.write((char*)&colorsSize, sizeof(unsigned));
sceneOutFile.write((char*)&indicesSize, sizeof(unsigned));
sceneOutFile.write((char*)&meshesSize, sizeof(unsigned));
if (verticesSize > 0) sceneOutFile.write((char*)&scene.vertices[0], sizeof(glm::vec3) * verticesSize);
if (uvsSize > 0) sceneOutFile.write((char*)&scene.uvs[0], sizeof(glm::vec2) * uvsSize);
if (normalsSize > 0) sceneOutFile.write((char*)&scene.normals[0], sizeof(glm::vec3) * normalsSize);
if (colorsSize > 0) sceneOutFile.write((char*)&scene.colors[0], sizeof(glm::vec3) * colorsSize);
if (indicesSize > 0) sceneOutFile.write((char*)&scene.indices[0], sizeof(unsigned) * indicesSize);
unsigned int textureSize;
for (Mesh mesh : scene.meshes) {
sceneOutFile.write((char*)&mesh.offset, sizeof(unsigned));
sceneOutFile.write((char*)&mesh.size, sizeof(unsigned));
textureSize = (unsigned)mesh.texture.size();
sceneOutFile.write((char*)&textureSize, sizeof(unsigned int));
sceneOutFile.write(mesh.texture.c_str(), textureSize);
sceneOutFile.write((char*)&mesh.hasUVs, sizeof(bool));
sceneOutFile.write((char*)&mesh.hasVertexColors, sizeof(bool));
sceneOutFile.write((char*)&mesh.reflectivity, sizeof(float));
}
sceneOutFile.close();
return true;
}