Finished reworking asset builder; Models are now cooked when built

This commit is contained in:
Grayson Riffe (Laptop) 2021-12-14 02:51:23 -06:00
parent cc0316ff80
commit 7a93befa14
20 changed files with 291 additions and 475 deletions

View File

@ -62,6 +62,7 @@
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)src\include;$(ProjectDir)dep\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -79,6 +80,7 @@
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)src\include;$(ProjectDir)dep\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -91,13 +93,11 @@
<ItemGroup>
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\Models.cpp" />
<ClCompile Include="src\Textures.cpp" />
<ClCompile Include="src\Utility.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
<ClInclude Include="src\include\Models.h" />
<ClInclude Include="src\include\Textures.h" />
<ClInclude Include="src\include\Utility.h" />
</ItemGroup>
<ItemGroup>

View File

@ -18,9 +18,6 @@
<ClCompile Include="src\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Textures.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Models.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -32,9 +29,6 @@
<ClInclude Include="src\include\Utility.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\Textures.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\Models.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -4,6 +4,7 @@
#include <sstream>
#include <filesystem>
#include <map>
#include <set>
void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
std::vector<char> obj(&OBJin[0], &OBJin[0] + OBJin.size());
@ -156,8 +157,18 @@ void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
int matCount = 0;
std::string modelHeader;
int numMats = (int)mats.size();
modelHeader.append((char*)&numMats, sizeof(numMats));
std::vector<std::string> textures = getNeededTextures(MTLin);
std::string textureHeader;
if (textures.empty())
textureHeader = "none\n";
else
for (const auto& curr : textures)
textureHeader.append(curr + (std::string)"\n");
modelHeader.append(textureHeader);
modelHeader.append("/ENDTEXTURES\n");
modelHeader.append(std::to_string(mats.size()) + (std::string)"\n");
for (auto& m : mats) {
std::string curr = m.first;
@ -192,13 +203,25 @@ void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
TempMaterial& curr2 = *m.second;
//Serialize this
//curr2.diffuseColor.x, curr2.diffuseColor.y, curr2.diffuseColor.z, curr2.shininess
std::string textureIndices;
if (!curr2.diffuseTextureName.empty())
textureIndices.append(std::to_string((std::find(textures.begin(), textures.end(), curr2.diffuseTextureName) - textures.begin()) + 1) + (std::string)" ");
else
textureIndices.append(std::to_string(0) + (std::string)" ");
if (!curr2.specularTextureName.empty())
textureIndices.append(std::to_string((std::find(textures.begin(), textures.end(), curr2.specularTextureName) - textures.begin()) + 1) + (std::string)" ");
else
textureIndices.append(std::to_string(0) + (std::string)" ");
if (!curr2.normalTextureName.empty())
textureIndices.append(std::to_string((std::find(textures.begin(), textures.end(), curr2.normalTextureName) - textures.begin()) + 1) + (std::string)" ");
else
textureIndices.append(std::to_string(0) + (std::string)" ");
modelHeader.append((char*)&curr2.diffuseColor.x, sizeof(curr2.diffuseColor.x));
modelHeader.append((char*)&curr2.diffuseColor.y, sizeof(curr2.diffuseColor.y));
modelHeader.append((char*)&curr2.diffuseColor.z, sizeof(curr2.diffuseColor.z));
modelHeader.append((char*)&curr2.shininess, sizeof(curr2.shininess));
modelHeader.append(textureIndices);
modelHeader.append(std::to_string(curr2.diffuseColor.x) + (std::string)" ");
modelHeader.append(std::to_string(curr2.diffuseColor.y) + (std::string)" ");
modelHeader.append(std::to_string(curr2.diffuseColor.z) + (std::string)" ");
modelHeader.append(std::to_string(curr2.shininess) + (std::string)"\n");
size_t offset = vboPositions.size() / 3;
vboPositions.insert(vboPositions.end(), curr2.outVB.begin(), curr2.outVB.end());
@ -212,20 +235,23 @@ void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
delete m.second;
matCount++;
}
modelHeader.append("/ENDMATERIALS\n");
size_t posSize = vboPositions.size() * sizeof(float);
size_t tcSize = vboTexCoords.size() * sizeof(float);
size_t normSize = vboNormals.size() * sizeof(float);
size_t tanSize = vboTangents.size() * sizeof(float);
size_t matIndicesSize = vboMaterialIndices.size() * sizeof(int);
size_t indicesSize = vboIndices.size() * sizeof(unsigned int);
unsigned int posSize = (unsigned int)vboPositions.size() * sizeof(float);
unsigned int tcSize = (unsigned int)vboTexCoords.size() * sizeof(float);
unsigned int normSize = (unsigned int)vboNormals.size() * sizeof(float);
unsigned int tanSize = (unsigned int)vboTangents.size() * sizeof(float);
unsigned int matIndicesSize = (unsigned int)vboMaterialIndices.size() * sizeof(int);
unsigned int indicesSize = (unsigned int)vboIndices.size() * sizeof(unsigned int);
modelHeader.append((char*)&posSize, sizeof(posSize));
modelHeader.append((char*)&tcSize, sizeof(tcSize));
modelHeader.append((char*)&normSize, sizeof(normSize));
modelHeader.append((char*)&tanSize, sizeof(tanSize));
modelHeader.append((char*)&matIndicesSize, sizeof(matIndicesSize));
modelHeader.append((char*)&indicesSize, sizeof(indicesSize));
modelHeader.append(std::to_string(posSize) + (std::string)" ");
modelHeader.append(std::to_string(tcSize) + (std::string)" ");
modelHeader.append(std::to_string(normSize) + (std::string)" ");
modelHeader.append(std::to_string(tanSize) + (std::string)" ");
modelHeader.append(std::to_string(matIndicesSize) + (std::string)" ");
modelHeader.append(std::to_string(vboIndices.size()) + (std::string)"\n");
modelHeader.append("/ENDHEADER\n");
out.append(modelHeader);
out.append((char*)vboPositions.data(), posSize);
@ -278,7 +304,8 @@ void parseMaterials(std::unordered_map<std::string, TempMaterial*>& mats, std::v
}
}
void getNeededImages(std::string mtl, std::set<std::string>& set) {
std::vector<std::string> getNeededTextures(std::string mtl) {
std::set<std::string> tex;
while (mtl.size()) {
size_t pos = mtl.find("map_");
if (pos == std::string::npos)
@ -292,6 +319,15 @@ void getNeededImages(std::string mtl, std::set<std::string>& set) {
size_t pos2 = temp.find_last_of("/\\");
if (pos2 != std::string::npos)
temp = temp.substr(pos2 + 1);
set.insert(temp);
tex.insert(temp);
}
std::vector<std::string> out;
if (tex.empty())
return out;
else
for (const auto& curr : tex)
out.push_back(curr);
return out;
}

View File

@ -1,18 +0,0 @@
#include "Textures.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
void cookTexture(const std::string& in, std::string& out) {
stbi_set_flip_vertically_on_load(true);
int x, y, channels;
unsigned char* texture = stbi_load_from_memory((unsigned char*)&in[0], (int)in.size(), &x, &y, &channels, 0);
out.append((char*)&x, sizeof(x));
out.append((char*)&y, sizeof(y));
out.append((char*)&channels, sizeof(channels));
out.append((char*)texture, x * y * channels);
stbi_image_free(texture);
}

View File

@ -56,8 +56,6 @@ void writePack(const std::string& filename, std::string& in) {
if (!out)
Error("Pack \"" + filename + (std::string)"\" could not be written!");
in.insert(0, "NFASSETPACK");
Log("Encrypting...");
for (unsigned int i = 0; i < in.size(); i++)
in[i] += 100;
@ -80,5 +78,8 @@ std::string getNewLine(std::stringstream& stringstream) {
if (out[out.size() - 1] == '\r')
out.erase(out.size() - 1);
if (out[0] == ' ')
out = out.substr(1);
return out;
}

View File

@ -1,6 +1,4 @@
#pragma once
#include <string>
#include <set>
#include <unordered_map>
#include <vector>
@ -30,4 +28,4 @@ struct TempMaterial {
void cookModel(std::string& in, std::string& MTLin, std::string& out);
void parseMaterials(std::unordered_map<std::string, TempMaterial*>& mats, std::vector<char>& mtl);
void getNeededImages(std::string mtl, std::set<std::string>& set);
std::vector<std::string> getNeededTextures(std::string mtl);

View File

@ -1,4 +0,0 @@
#pragma once
#include <string>
void cookTexture(const std::string& in, std::string& out);

View File

@ -1,25 +1,29 @@
#include <iostream>
#include <thread>
#include <filesystem>
#include <set>
#include <unordered_map>
#include <Windows.h>
#include <compressapi.h>
#include "Utility.h"
#include "Models.h"
#include "Textures.h"
[[noreturn]]
void printHelp() {
std::cout << "Nothin' Fancy Asset Builder\n\nThis tool creates .nfpack files for the NF engine to "
"load at runtime. A pack gets created for each directory in the working directory if there "
"are only compatible files inside. Subdirectories are not ignored.\n\nFor more information, "
"refer to the Nothin' Fancy manual";
std::exit(0);
}
int main(int argc, char* argv[]) {
Log("Starting up");
if (argc > 1 && ((std::string)argv[1] == "-h" || (std::string)argv[1] == "/?"))
printHelp();
if (argc > 1)
if ((std::string)argv[1] == "-h") {
Log("Nothin' Fancy Asset Builder\nThis tool creates .nfpack files for the NF engine to load "
"at runtime.\nA pack gets created for each directory in the working directory if there "
"are only compatible files inside.\nSubdirectories are not ignored.");
return 0;
}
Log("Starting up");
initCompressor();
@ -35,7 +39,8 @@ int main(int argc, char* argv[]) {
std::string currPackFilename = currDir.path().filename().string().append(".nfpack");
Log("Building pack " + currPackFilename);
std::unordered_map<std::string, size_t> packFiles;
std::vector<std::string> packFilenames;
std::vector<unsigned int> packFileSizes;
std::string currFileExtension;
std::string currFileIn;
std::string currPackOut;
@ -47,8 +52,8 @@ int main(int argc, char* argv[]) {
std::filesystem::path relative = std::filesystem::relative(curr, currDir);
std::string currFileName = relative.filename().string();
for (auto& file : packFiles)
if (currFileName == file.first)
for (auto& file : packFilenames)
if (currFileName == file)
Error("Duplicate asset \"" + currFileName + (std::string)"\" in pack!");
currFileExtension = relative.extension().string().substr(1);
@ -77,10 +82,11 @@ int main(int argc, char* argv[]) {
Log("Cooking model...");
cookModel(currFileIn, mtl, currFileOut);
}
else if (currFileExtension == "png" || currFileExtension == "jpg")
cookTexture(currFileIn, currFileOut);
else
currFileOut = currFileIn;
packFiles[currFileName] = currFileOut.size();
packFilenames.push_back(currFileName);
packFileSizes.push_back((unsigned int)currFileOut.size());
currPackOut += currFileOut;
@ -94,19 +100,16 @@ int main(int argc, char* argv[]) {
else
Log("Finished gathering files");
//Write pack header with asset names and sizes
std::string header;
for (auto& currFile : packFiles) {
header += currFile.first;
header += ':';
header.append((char*)&currFile.second, sizeof(size_t));
header += ':';
header += std::to_string(fileCount) + (std::string)"\n";
for (unsigned int i = 0; i < packFilenames.size(); i++) {
header += packFilenames[i];
header += '\n';
header += std::to_string(packFileSizes[i]);
header += '\n';
}
header.erase(header.size() - 1);
header.append("/NFENDOFPACKHEADER");
int headerTableSize = (int)header.size();
header.insert(0, (char*)&headerTableSize, sizeof(headerTableSize));
header.insert(0, (char*)&fileCount, sizeof(fileCount));
header.append("/ENDHEADER");
currPackOut.insert(0, header);
writePack(currPackFilename, currPackOut);

View File

@ -8,9 +8,9 @@ out vec4 color;
void main() {
vec3 tc;
tc = vec3(-texCoord.x, texCoord.y, texCoord.z);
if (texCoord.y > 0.999999 || texCoord.y < -0.999999) {
tc = vec3(-texCoord.x, -texCoord.y, texCoord.z);
if (texCoord.y > 0.999999 || texCoord.y < -0.999999)
tc = vec3(texCoord.x, texCoord.y, texCoord.z);
}
color = texture(cm, tc);
}

View File

@ -51,34 +51,37 @@ namespace nf {
}
void AssetPack::load(const char* packName) {
NFLog("Loading asset pack \"" + (std::string)packName + (std::string)"\"");
std::string path = "assets/" + (std::string)packName;
std::string packContents = readFile(path, true);
std::string packContents;
if (!readFile(path, packContents, true))
NFError("Could not find pack file \"" + (std::string)packName + (std::string)"\"!") ;
std::string packContentsOBJ = packContents;
std::unordered_map<std::string, ACubemap*> cubemaps;
std::unordered_map<std::string, AButton*> buttons;
unsigned int cubemapCount = 0;
unsigned int buttonCount = 0;
while (packContents.size()) {
packContents = packContents.substr(9);
size_t endAssetNamePos = packContents.find_first_of('\n');
std::string assetName = packContents.substr(0, endAssetNamePos);
packContents = packContents.substr(endAssetNamePos + 1);
size_t extensionPos = assetName.find_first_of('.');
std::string extension = assetName.substr(extensionPos + 1);
std::string assetContents;
size_t nextAssetPos = packContents.find("#NFASSET ");
if (nextAssetPos != std::string::npos) {
assetContents = packContents.substr(0, nextAssetPos - 1);
packContents = packContents.substr(nextAssetPos);
}
else {
assetContents = packContents;
packContents = "";
}
unsigned int assetSize = (unsigned int)assetContents.size();
unsigned int cubemapFaceCount = 0;
unsigned int buttonTextureCount = 0;
if (extension == "obj")
unsigned int assetCount = std::stoi(packContents.substr(0, packContents.find_first_of("\n")));
unsigned int endHeader = (unsigned int)packContents.find("/ENDHEADER");
unsigned int headerLength = endHeader - ((unsigned int)packContents.find_first_of("\n") + 1);
std::stringstream header(packContents.substr(packContents.find_first_of("\n") + 1, headerLength));
unsigned int assetPos = endHeader + 10;
for (unsigned int i = 0; i < assetCount; i++) {
std::string assetName;
std::getline(header, assetName);
std::string temp;
std::getline(header, temp);
unsigned int assetSize = std::stoi(temp);
std::string extension = assetName.substr(assetName.find_last_of(".") + 1);
if (extension == "obj") {
assetPos += assetSize;
continue;
}
if (extension == "png" || extension == "jpg") {
if (assetName.find("_cmfront") != std::string::npos || assetName.find("_cmback") != std::string::npos || assetName.find("_cmtop") != std::string::npos || assetName.find("_cmbottom") != std::string::npos || assetName.find("_cmleft") != std::string::npos || assetName.find("_cmright") != std::string::npos) {
std::string cmName = assetName.substr(0, assetName.find('_'));
@ -91,40 +94,41 @@ namespace nf {
NFError("Duplicate cubemap images in pack \"" + (std::string)packName + (std::string)"\"!");
if (assetName.find("_cmfront") != std::string::npos) {
curr->frontData = new char[assetSize];
std::memcpy(curr->frontData, &assetContents[0], assetSize);
std::memcpy(curr->frontData, &packContents[assetPos], assetSize);
curr->frontSize = assetSize;
}
if (assetName.find("_cmback") != std::string::npos) {
curr->backData = new char[assetSize];
std::memcpy(curr->backData, &assetContents[0], assetSize);
std::memcpy(curr->backData, &packContents[assetPos], assetSize);
curr->backSize = assetSize;
}
if (assetName.find("_cmtop") != std::string::npos) {
curr->topData = new char[assetSize];
std::memcpy(curr->topData, &assetContents[0], assetSize);
std::memcpy(curr->topData, &packContents[assetPos], assetSize);
curr->topSize = assetSize;
}
if (assetName.find("_cmbottom") != std::string::npos) {
curr->bottomData = new char[assetSize];
std::memcpy(curr->bottomData, &assetContents[0], assetSize);
std::memcpy(curr->bottomData, &packContents[assetPos], assetSize);
curr->bottomSize = assetSize;
}
if (assetName.find("_cmleft") != std::string::npos) {
curr->leftData = new char[assetSize];
std::memcpy(curr->leftData, &assetContents[0], assetSize);
std::memcpy(curr->leftData, &packContents[assetPos], assetSize);
curr->leftSize = assetSize;
}
if (assetName.find("_cmright") != std::string::npos) {
curr->rightData = new char[assetSize];
std::memcpy(curr->rightData, &assetContents[0], assetSize);
std::memcpy(curr->rightData, &packContents[assetPos], assetSize);
curr->rightSize = assetSize;
}
assetPos += assetSize;
curr->numImages++;
if (curr->numImages == 6)
m_assets[cmName + (std::string)".cm"] = curr;
cubemapCount++;
cubemapFaceCount++;
continue;
}
else if (assetName.find("_buttonidle") != std::string::npos || assetName.find("_buttonhover") != std::string::npos || assetName.find("_buttonpressed") != std::string::npos) {
@ -139,30 +143,32 @@ namespace nf {
NFError("Duplicate button images in pack \"" + (std::string)packName + (std::string)"\"!");
if (assetName.find("_buttonidle") != std::string::npos) {
curr->idleTex.data = new char[assetSize];
std::memcpy(curr->idleTex.data, &assetContents[0], assetSize);
std::memcpy(curr->idleTex.data, &packContents[assetPos], assetSize);
curr->idleTex.size = assetSize;
}
if (assetName.find("_buttonhover") != std::string::npos) {
curr->hoverTex.data = new char[assetSize];
std::memcpy(curr->hoverTex.data, &assetContents[0], assetSize);
std::memcpy(curr->hoverTex.data, &packContents[assetPos], assetSize);
curr->hoverTex.size = assetSize;
}
if (assetName.find("_buttonpressed") != std::string::npos) {
curr->pressedTex.data = new char[assetSize];
std::memcpy(curr->pressedTex.data, &assetContents[0], assetSize);
std::memcpy(curr->pressedTex.data, &packContents[assetPos], assetSize);
curr->pressedTex.size = assetSize;
}
assetPos += assetSize;
curr->numImages++;
if (curr->numImages == 3)
m_assets[buttonName + (std::string)".button"] = curr;
buttonCount++;
buttonTextureCount++;
continue;
}
ATexture* texture = new ATexture;
texture->data = new char[assetSize];
std::memcpy(texture->data, &assetContents[0], assetSize);
std::memcpy(texture->data, &packContents[assetPos], assetSize);
assetPos += assetSize;
texture->size = assetSize;
if (packName == "base.nfpack")
texture->isBaseAsset = true;
@ -172,7 +178,8 @@ namespace nf {
if (extension == "shader") {
AShader* shader = new AShader;
shader->data = new char[assetSize + 1];
std::memcpy(shader->data, &assetContents[0], assetSize);
std::memcpy(shader->data, &packContents[assetPos], assetSize);
assetPos += assetSize;
shader->data[assetSize] = '\0';
m_assets[assetName] = shader;
continue;
@ -180,7 +187,8 @@ namespace nf {
if (extension == "ttf") {
AFont* font = new AFont;
font->data = new char[assetSize];
std::memcpy(font->data, &assetContents[0], assetSize);
std::memcpy(font->data, &packContents[assetPos], assetSize);
assetPos += assetSize;
font->size = assetSize;
if (packName == "base.nfpack")
font->isBaseAsset = true;
@ -190,7 +198,8 @@ namespace nf {
if (extension == "ogg" || extension == "wav") {
ASound* sound = new ASound;
sound->data = new char[assetSize];
std::memcpy(sound->data, &assetContents[0], assetSize);
std::memcpy(sound->data, &packContents[assetPos], assetSize);
assetPos += assetSize;
sound->size = assetSize;
if (packName == "base.nfpack")
sound->isBaseAsset = true;
@ -199,49 +208,50 @@ namespace nf {
}
NFError("Invalid asset extention in pack \"" + (std::string)packName + (std::string)"\"!");
}
if (cubemapCount % 6 != 0)
if (cubemapFaceCount % 6 != 0)
NFError("Could not find full cubemap in pack \"" + (std::string)packName + (std::string)"\"!");
if (buttonCount % 3 != 0)
if (buttonTextureCount % 3 != 0)
NFError("Could not find full button set in pack \"" + (std::string)packName + (std::string)"\"!");
while (packContentsOBJ.size()) {
packContentsOBJ = packContentsOBJ.substr(9);
size_t endAssetNamePos = packContentsOBJ.find_first_of('\n');
std::string assetName = packContentsOBJ.substr(0, endAssetNamePos);
packContentsOBJ = packContentsOBJ.substr(endAssetNamePos + 1);
size_t extensionPos = assetName.find_first_of('.');
std::string extension = assetName.substr(extensionPos + 1);
std::string assetContents;
size_t nextAssetPos = packContentsOBJ.find("#NFASSET ");
if (nextAssetPos != std::string::npos) {
assetContents = packContentsOBJ.substr(0, nextAssetPos - 1);
packContentsOBJ = packContentsOBJ.substr(nextAssetPos);
}
else {
assetContents = packContentsOBJ;
packContentsOBJ = "";
}
//Model pass after ATextures are loaded
assetPos = endHeader + 10;
std::stringstream header2(packContents.substr(packContents.find_first_of("\n") + 1, headerLength));
for (unsigned int i = 0; i < assetCount; i++) {
std::string assetName;
std::getline(header2, assetName);
std::string temp;
std::getline(header2, temp);
unsigned int assetSize = std::stoi(temp);
std::string extension = assetName.substr(assetName.find_last_of(".") + 1);
if (extension == "obj") {
AModel* model = new AModel;
std::string textures = assetContents.substr(0, assetContents.find("\n"));
std::string textures = packContents.substr(assetPos, packContents.find("/ENDTEXTURES", assetPos) - assetPos - 1);
if (textures != "none") {
std::stringstream ss(textures);
std::string curr;
while (ss >> curr) {
model->neededTextures[curr] = (ATexture*)m_assets[curr];
}
while (std::getline(ss, curr))
model->neededTextures.push_back((ATexture*)m_assets[curr]);
}
assetContents = assetContents.substr(assetContents.find("\n") + 1);
size_t assetSize = assetContents.size();
unsigned int newStartPos = (unsigned int)packContents.find("/ENDTEXTURES", assetPos) + 13;
assetSize -= newStartPos - assetPos;
assetPos = newStartPos;
model->data = new char[assetSize];
std::memcpy(model->data, &assetContents[0], assetSize);
std::memcpy(model->data, &packContents[assetPos], assetSize);
assetPos += assetSize;
model->size = assetSize;
if (packName == "base.nfpack")
model->isBaseAsset = true;
m_assets[assetName] = model;
continue;
}
assetPos += assetSize;
}
m_loaded = true;

View File

@ -41,17 +41,15 @@ namespace nf {
std::vector<CMFace> faces;
int tempWidth, tempHeight, tempNChannels;
unsigned char* tempData;
stbi_set_flip_vertically_on_load(false);
stbi_set_flip_vertically_on_load(true);
tempData = stbi_load_from_memory((unsigned char*)cm.leftData, cm.leftSize, &tempWidth, &tempHeight, &tempNChannels, 0);
faces.emplace_back(tempData, tempWidth, tempHeight, tempNChannels);
tempData = stbi_load_from_memory((unsigned char*)cm.rightData, cm.rightSize, &tempWidth, &tempHeight, &tempNChannels, 0);
faces.emplace_back(tempData, tempWidth, tempHeight, tempNChannels);
stbi_set_flip_vertically_on_load(true);
tempData = stbi_load_from_memory((unsigned char*)cm.topData, cm.topSize, &tempWidth, &tempHeight, &tempNChannels, 0);
faces.emplace_back(tempData, tempWidth, tempHeight, tempNChannels);
tempData = stbi_load_from_memory((unsigned char*)cm.bottomData, cm.bottomSize, &tempWidth, &tempHeight, &tempNChannels, 0);
faces.emplace_back(tempData, tempWidth, tempHeight, tempNChannels);
stbi_set_flip_vertically_on_load(false);
tempData = stbi_load_from_memory((unsigned char*)cm.backData, cm.backSize, &tempWidth, &tempHeight, &tempNChannels, 0);
faces.emplace_back(tempData, tempWidth, tempHeight, tempNChannels);
tempData = stbi_load_from_memory((unsigned char*)cm.frontData, cm.frontSize, &tempWidth, &tempHeight, &tempNChannels, 0);

View File

@ -171,11 +171,11 @@ namespace nf {
}
}
void PhysicsEngine::addConvexMesh(Model* model, std::vector<float>& vertices) {
void PhysicsEngine::addConvexMesh(Model* model, const float* vertices, unsigned int buffSize) {
PxConvexMeshDesc desc;
desc.points.count = (unsigned int)vertices.size() / 3;
desc.points.count = (unsigned int)buffSize / 12;
desc.points.stride = 3 * sizeof(float);
desc.points.data = &vertices[0];
desc.points.data = vertices;
desc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
PxDefaultMemoryOutputStream buf;
@ -187,14 +187,14 @@ namespace nf {
m_convexMeshes[model] = mesh;
}
void PhysicsEngine::addTriangleMesh(Model* model, std::vector<float>& vertices, std::vector<unsigned int>& indices) {
void PhysicsEngine::addTriangleMesh(Model* model, const float* vertices, unsigned int vertBuffSize, const unsigned int* indices, unsigned int indicesCount) {
PxTriangleMeshDesc desc;
desc.points.count = (unsigned int)vertices.size() / 3;
desc.points.count = (unsigned int)vertBuffSize / 12;
desc.points.stride = sizeof(float) * 3;
desc.points.data = &vertices[0];
desc.triangles.count = (unsigned int)indices.size() / 3;
desc.points.data = vertices;
desc.triangles.count = (unsigned int)indicesCount / 3;
desc.triangles.stride = sizeof(unsigned int) * 3;
desc.triangles.data = &indices[0];
desc.triangles.data = indices;
PxDefaultMemoryOutputStream buf;
if (!m_cooking->cookTriangleMesh(desc, buf))

View File

@ -14,293 +14,105 @@
namespace nf {
Model::Model(AModel* model, bool physicsConvex, bool physicsTriangle) :
m_base(model->isBaseAsset),
m_newMtl("newmtl"),
m_newLine("\n")
m_base(model->isBaseAsset)
{
if (model->neededTextures.size() > 32)
NFError("Model exceedes 32 texture limit!");
std::vector<char> file(model->data, model->data + model->size);
size_t mtlPos = std::search(file.begin(), file.end(), m_newMtl, m_newMtl + std::strlen(m_newMtl)) - file.begin();
std::vector<char> mtl(&file[mtlPos], &file[0] + file.size());
std::unordered_map<std::string, TempMaterial*> mats;
parseMaterials(mats, mtl);
std::string modelData(model->data, model->data + model->size);
std::string mats = modelData.substr(0, modelData.find("/ENDMATERIALS") - 1);
std::vector<char> obj(&file[0], &file[mtlPos]);
std::vector<float> vbRaw, tcRaw, vnRaw;
std::string usingMat;
createMaterials(mats, model);
bool tcPresent = false, vnPresent = false;
size_t position = 0;
while (true) {
size_t nextLine = std::search(obj.begin() + position, obj.end(), m_newLine, m_newLine + std::strlen(m_newLine)) - (obj.begin() + position);
if (!nextLine)
break;
std::vector<char> line(&obj[position], &obj[position + nextLine]);
position += nextLine + 1;
std::stringstream ss(std::string(&line[0], line.size()));
std::string firstWord;
ss >> firstWord;
unsigned int vboSizesStart = (unsigned int)modelData.find("/ENDMATERIALS") + 14;
std::string vboSizes = modelData.substr(vboSizesStart, modelData.find("/ENDHEADER") - vboSizesStart - 1);
if (std::strcmp(&firstWord[0], "v") == 0) {
float x = 0.0f, y = 0.0f, z = 0.0f;
ss >> x >> y >> z;
vbRaw.push_back(x);
vbRaw.push_back(y);
vbRaw.push_back(z);
}
else if (std::strcmp(&firstWord[0], "vt") == 0) {
tcPresent = true;
float u = 0.0f, v = 0.0f;
ss >> u >> v;
tcRaw.push_back(u);
tcRaw.push_back(v);
}
else if (std::strcmp(&firstWord[0], "vn") == 0) {
vnPresent = true;
float x = 0.0f, y = 0.0f, z = 0.0f;
ss >> x >> y >> z;
vnRaw.push_back(x);
vnRaw.push_back(y);
vnRaw.push_back(z);
}
else if (std::strcmp(&firstWord[0], "usemtl") == 0) {
std::string matName;
ss >> matName;
usingMat = matName;
}
else if (std::strcmp(&firstWord[0], "f") == 0) {
if (!tcPresent)
NFError("No texture coordinates found in model!");
if (!vnPresent)
NFError("No normals found in model!");
unsigned int currPos = (unsigned int)modelData.find("/ENDHEADER") + 11;
unsigned int currSize = 0;
std::stringstream ss(vboSizes);
unsigned int vertexIndex[3], uvIndex[3], vnIndex[3];
char temp;
ss >> vertexIndex[0] >> temp >> uvIndex[0] >> temp >> vnIndex[0] >> vertexIndex[1] >> temp >> uvIndex[1] >> temp >> vnIndex[1] >> vertexIndex[2] >> temp >> uvIndex[2] >> temp >> vnIndex[2];
if (ss.rdbuf()->in_avail() > 1)
NFError("Model has non-triangle faces!");
mats[usingMat]->vbIndices.push_back(vertexIndex[0]);
mats[usingMat]->vbIndices.push_back(vertexIndex[1]);
mats[usingMat]->vbIndices.push_back(vertexIndex[2]);
mats[usingMat]->tcIndices.push_back(uvIndex[0]);
mats[usingMat]->tcIndices.push_back(uvIndex[1]);
mats[usingMat]->tcIndices.push_back(uvIndex[2]);
mats[usingMat]->vnIndices.push_back(vnIndex[0]);
mats[usingMat]->vnIndices.push_back(vnIndex[1]);
mats[usingMat]->vnIndices.push_back(vnIndex[2]);
}
}
float* pos;
unsigned int posBuffSize;
unsigned int* indices;
unsigned int indicesCount;
for (auto& m : mats) {
std::string curr = m.first;
for (unsigned int i = 0; i < mats[curr]->vbIndices.size(); i++) {
unsigned int vertexIndex = mats[curr]->vbIndices[i];
unsigned int uvIndex = mats[curr]->tcIndices[i];
unsigned int vnIndex = mats[curr]->vnIndices[i];
float vertexX = vbRaw[(vertexIndex - 1) * 3];
float vertexY = vbRaw[(vertexIndex - 1) * 3 + 1];
float vertexZ = vbRaw[(vertexIndex - 1) * 3 + 2];
float vertexU = tcRaw[(uvIndex - 1) * 2];
float vertexV = tcRaw[(uvIndex - 1) * 2 + 1];
float vnX = vnRaw[(vnIndex - 1) * 3];
float vnY = vnRaw[(vnIndex - 1) * 3 + 1];
float vnZ = vnRaw[(vnIndex - 1) * 3 + 2];
mats[curr]->unindexedVB.push_back(vertexX);
mats[curr]->unindexedVB.push_back(vertexY);
mats[curr]->unindexedVB.push_back(vertexZ);
mats[curr]->unindexedTC.push_back(vertexU);
mats[curr]->unindexedTC.push_back(vertexV);
mats[curr]->unindexedVN.push_back(vnX);
mats[curr]->unindexedVN.push_back(vnY);
mats[curr]->unindexedVN.push_back(vnZ);
}
for (unsigned int i = 0; i * 9 < mats[curr]->unindexedVB.size(); i++) {
glm::vec3 pos1(mats[curr]->unindexedVB[i * 9], mats[curr]->unindexedVB[i * 9 + 1], mats[curr]->unindexedVB[i * 9 + 2]);
glm::vec2 uv1(mats[curr]->unindexedTC[i * 6], mats[curr]->unindexedTC[i * 6 + 1]);
glm::vec3 pos2(mats[curr]->unindexedVB[i * 9 + 3], mats[curr]->unindexedVB[i * 9 + 4], mats[curr]->unindexedVB[i * 9 + 5]);
glm::vec2 uv2(mats[curr]->unindexedTC[i * 6 + 2], mats[curr]->unindexedTC[i * 6 + 3]);
glm::vec3 pos3(mats[curr]->unindexedVB[i * 9 + 6], mats[curr]->unindexedVB[i * 9 + 7], mats[curr]->unindexedVB[i * 9 + 8]);
glm::vec2 uv3(mats[curr]->unindexedTC[i * 6 + 4], mats[curr]->unindexedTC[i * 6 + 5]);
glm::vec3 edge1 = pos2 - pos1;
glm::vec3 edge2 = pos3 - pos1;
glm::vec2 delta1 = uv2 - uv1;
glm::vec2 delta2 = uv3 - uv1;
float f = 1.0f / (delta1.x * delta2.y - delta2.x * delta1.y);
float x = f * (delta2.y * edge1.x - delta1.y * edge2.x);
float y = f * (delta2.y * edge1.y - delta1.y * edge2.y);
float z = f * (delta2.y * edge1.z - delta1.y * edge2.z);
mats[curr]->unindexedTan.push_back(x);
mats[curr]->unindexedTan.push_back(y);
mats[curr]->unindexedTan.push_back(z);
mats[curr]->unindexedTan.push_back(x);
mats[curr]->unindexedTan.push_back(y);
mats[curr]->unindexedTan.push_back(z);
mats[curr]->unindexedTan.push_back(x);
mats[curr]->unindexedTan.push_back(y);
mats[curr]->unindexedTan.push_back(z);
}
}
struct Vertex {
float x;
float y;
float z;
float u;
float v;
float vnX;
float vnY;
float vnZ;
bool operator<(const Vertex other) const {
return std::memcmp((void*)this, (void*)&other, sizeof(Vertex)) > 0;
}
};
std::vector<float> vboPositions;
std::vector<float> vboTexCoords;
std::vector<float> vboNormals;
std::vector<float> vboTangents;
std::vector<int> vboMaterialIndices;
std::vector<unsigned int> vboIndices;
int matCount = 0;
for (auto& m : mats) {
std::string curr = m.first;
std::map<Vertex, unsigned int> vertexMap;
for (unsigned int i = 0; i * 3 < mats[curr]->unindexedVB.size(); i++) {
Vertex currVertex = { mats[curr]->unindexedVB[(i * 3)], mats[curr]->unindexedVB[(i * 3) + 1], mats[curr]->unindexedVB[(i * 3) + 2], mats[curr]->unindexedTC[(i * 2)], mats[curr]->unindexedTC[(i * 2) + 1], mats[curr]->unindexedVN[(i * 3)], mats[curr]->unindexedVN[(i * 3) + 1], mats[curr]->unindexedVN[(i * 3) + 2] };
bool found = false;
found = vertexMap.find(currVertex) != vertexMap.end();
if (found) {
unsigned int index = vertexMap[currVertex];
mats[curr]->outIB.push_back(index);
mats[curr]->ibCount++;
}
else {
mats[curr]->outVB.push_back(currVertex.x);
mats[curr]->outVB.push_back(currVertex.y);
mats[curr]->outVB.push_back(currVertex.z);
mats[curr]->outTC.push_back(currVertex.u);
mats[curr]->outTC.push_back(currVertex.v);
mats[curr]->outVN.push_back(currVertex.vnX);
mats[curr]->outVN.push_back(currVertex.vnY);
mats[curr]->outVN.push_back(currVertex.vnZ);
mats[curr]->outTan.push_back(mats[curr]->unindexedTan[(i * 3)]);
mats[curr]->outTan.push_back(mats[curr]->unindexedTan[(i * 3 + 1)]);
mats[curr]->outTan.push_back(mats[curr]->unindexedTan[(i * 3 + 2)]);
size_t index = (mats[curr]->outVB.size() / 3) - 1;
mats[curr]->outIB.push_back((unsigned int)index);
vertexMap[currVertex] = (unsigned int)index;
mats[curr]->ibCount++;
}
}
TempMaterial& curr2 = *m.second;
ATexture* diffA = nullptr;
Texture* diff = nullptr;
if (curr2.diffuseTextureName.size()) {
diffA = model->neededTextures[curr2.diffuseTextureName];
diff = new Texture(diffA);
}
ATexture* specA = nullptr;
Texture* spec = nullptr;
if (curr2.specularTextureName.size()) {
specA = model->neededTextures[curr2.specularTextureName];
spec = new Texture(specA, true);
}
ATexture* normA = nullptr;
Texture* norm = nullptr;
if (curr2.normalTextureName.size()) {
normA = model->neededTextures[curr2.normalTextureName];
norm = new Texture(normA, true);
}
m_materials.push_back(std::make_tuple(diff, spec, norm, curr2.diffuseColor.x, curr2.diffuseColor.y, curr2.diffuseColor.z, curr2.shininess));
size_t offset = vboPositions.size() / 3;
vboPositions.insert(vboPositions.end(), curr2.outVB.begin(), curr2.outVB.end());
vboTexCoords.insert(vboTexCoords.end(), curr2.outTC.begin(), curr2.outTC.end());
vboNormals.insert(vboNormals.end(), curr2.outVN.begin(), curr2.outVN.end());
vboTangents.insert(vboTangents.end(), curr2.outTan.begin(), curr2.outTan.end());
vboMaterialIndices.insert(vboMaterialIndices.end(), curr2.outVB.size() / 3, matCount);
if (offset)
std::for_each(curr2.outIB.begin(), curr2.outIB.end(), [offset](unsigned int& out) { out += (unsigned int)offset; });
vboIndices.insert(vboIndices.end(), curr2.outIB.begin(), curr2.outIB.end());
delete m.second;
matCount++;
}
if (m_materials.size() > 32)
NFError("Model exceedes 32 material limit!");
m_vao = new VertexArray;
m_vao->addBuffer(&vboPositions[0], vboPositions.size() * sizeof(float));
//Positions
ss >> currSize;
pos = (float*)&modelData[currPos];
posBuffSize = currSize;
m_vao->addBuffer(&modelData[currPos], currSize);
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboTexCoords[0], vboTexCoords.size() * sizeof(float));
currPos += currSize;
//Texture coordinates
ss >> currSize;
m_vao->addBuffer(&modelData[currPos], currSize);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboNormals[0], vboNormals.size() * sizeof(float));
currPos += currSize;
//Normals
ss >> currSize;
m_vao->addBuffer(&modelData[currPos], currSize);
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboTangents[0], vboTangents.size() * sizeof(float));
currPos += currSize;
//Tangents
ss >> currSize;
m_vao->addBuffer(&modelData[currPos], currSize);
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboMaterialIndices[0], vboMaterialIndices.size() * sizeof(int));
currPos += currSize;
//Material indices
ss >> currSize;
m_vao->addBuffer(&modelData[currPos], currSize);
m_vao->pushInt(1);
m_vao->finishBufferLayout();
m_ib = new IndexBuffer(&vboIndices[0], vboIndices.size());
currPos += currSize;
//Vertex indices
ss >> currSize;
indices = (unsigned int*)&modelData[currPos];
indicesCount = currSize;
m_ib = new IndexBuffer(&modelData[currPos], currSize);
if (physicsConvex)
Application::getApp()->getPhysicsEngine()->addConvexMesh(this, vboPositions);
Application::getApp()->getPhysicsEngine()->addConvexMesh(this, pos, posBuffSize);
else if(physicsTriangle)
Application::getApp()->getPhysicsEngine()->addTriangleMesh(this, vboPositions, vboIndices);
Application::getApp()->getPhysicsEngine()->addTriangleMesh(this, pos, posBuffSize, indices, indicesCount);
}
void Model::parseMaterials(std::unordered_map<std::string, TempMaterial*>& mats, std::vector<char>& mtl) {
std::string currMat;
size_t position = 0;
while (true) {
size_t nextLine = std::search(mtl.begin() + position, mtl.end(), m_newLine, m_newLine + std::strlen(m_newLine)) - (mtl.begin() + position);
if (position + nextLine >= mtl.size())
break;
std::vector<char> line(&mtl[position], &mtl[position + nextLine]);
position += nextLine + 1;
std::stringstream ss(std::string(&line[0], line.size()));
std::string firstWord;
ss >> firstWord;
void Model::createMaterials(const std::string& mats, AModel* model) {
std::stringstream ss(mats);
std::string temp;
std::getline(ss, temp);
unsigned int matCount = std::stoi(temp);
if (matCount > 32)
NFError("Model exceedes 32 material limit!");
if (std::strcmp(&firstWord[0], "newmtl") == 0) {
std::string matName;
ss >> matName;
currMat = matName;
mats[currMat] = new TempMaterial;
}
else if (std::strcmp(&firstWord[0], "Kd") == 0) {
float r = 0.0f, g = 0.0f, b = 0.0f;
ss >> r >> g >> b;
mats[currMat]->diffuseColor = Vec3(r, g, b);
}
else if (std::strcmp(&firstWord[0], "map_Kd") == 0) {
std::string texName;
ss >> texName;
mats[currMat]->diffuseTextureName = texName;
}
else if (std::strcmp(&firstWord[0], "map_Ks") == 0) {
std::string texName;
ss >> texName;
mats[currMat]->specularTextureName = texName;
}
else if (std::strcmp(&firstWord[0], "map_Bump") == 0) {
std::string texName;
ss >> texName;
mats[currMat]->normalTextureName = texName;
}
else if (std::strcmp(&firstWord[0], "Ns") == 0) {
float s = 0.0f;
ss >> s;
mats[currMat]->shininess = s;
}
for (unsigned int i = 0; i < matCount; i++) {
Material curr;
unsigned int texIndex;
ss >> texIndex;
if (texIndex != 0)
curr.diffuse = new Texture(model->neededTextures[texIndex - 1]);
else
curr.diffuse = nullptr;
ss >> texIndex;
if (texIndex != 0)
curr.specular = new Texture(model->neededTextures[texIndex - 1], true);
else
curr.specular = nullptr;
ss >> texIndex;
if (texIndex != 0)
curr.normal = new Texture(model->neededTextures[texIndex - 1], true);
else
curr.normal = nullptr;
ss >> curr.diffuseColor.x >> curr.diffuseColor.y >> curr.diffuseColor.z >> curr.shininess;
m_materials.push_back(curr);
}
}
@ -320,7 +132,7 @@ namespace nf {
for (unsigned int i = 0; i < m_materials.size(); i++) {
std::string currMatSuffix = std::to_string(i) + (std::string)"]";
Texture* diff;
if ((diff = std::get<0>(m_materials[i])) != nullptr) {
if ((diff = m_materials[i].diffuse) != nullptr) {
shader->setUniform(m_hasDiffString + currMatSuffix, true);
diff->bind(texSlot);
shader->setUniform(m_diffString + currMatSuffix, texSlot);
@ -328,11 +140,11 @@ namespace nf {
}
else {
shader->setUniform(m_hasDiffString + currMatSuffix, false);
glm::vec3 color(std::get<3>(m_materials[i]), std::get<4>(m_materials[i]), std::get<5>(m_materials[i]));
glm::vec3 color(m_materials[i].diffuseColor.x, m_materials[i].diffuseColor.y, m_materials[i].diffuseColor.z);
shader->setUniform(m_diffColorString + currMatSuffix, color);
}
Texture* spec;
if ((spec = std::get<1>(m_materials[i])) != nullptr) {
if ((spec = m_materials[i].specular) != nullptr) {
shader->setUniform(m_hasSpecString + currMatSuffix, true);
spec->bind(texSlot);
shader->setUniform(m_specString + currMatSuffix, texSlot);
@ -341,7 +153,7 @@ namespace nf {
else
shader->setUniform(m_hasSpecString + currMatSuffix, false);
Texture* norm;
if ((norm = std::get<2>(m_materials[i])) != nullptr) {
if ((norm = m_materials[i].normal) != nullptr) {
shader->setUniform(m_hasNormString + currMatSuffix, true);
norm->bind(texSlot);
shader->setUniform(m_normString + currMatSuffix, texSlot);
@ -349,7 +161,7 @@ namespace nf {
}
else
shader->setUniform(m_hasNormString + currMatSuffix, false);
shader->setUniform(m_specPowerString + currMatSuffix, std::get<6>(m_materials[i]));
shader->setUniform(m_specPowerString + currMatSuffix, m_materials[i].shininess);
}
}
@ -360,11 +172,11 @@ namespace nf {
Model::~Model() {
for (unsigned int i = 0; i < m_materials.size(); i++) {
Texture* curr;
if ((curr = std::get<0>(m_materials[i])) != nullptr)
if ((curr = m_materials[i].diffuse) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(curr);
if ((curr = std::get<1>(m_materials[i])) != nullptr)
if ((curr = m_materials[i].specular) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(curr);
if ((curr = std::get<2>(m_materials[i])) != nullptr)
if ((curr = m_materials[i].normal) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(curr);
}
}

View File

@ -1,6 +1,8 @@
#include "nf/Texture.h"
#include "GL/glew.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "nf/Assets.h"
#include "nf/Utility.h"
@ -12,14 +14,18 @@ namespace nf {
m_x(0),
m_y(0)
{
//Load dimensions and channels from cooked data
int nChannels;
stbi_set_flip_vertically_on_load(true);
unsigned char* texture = stbi_load_from_memory((unsigned char*)tex->data, (unsigned int)tex->size, &m_x, &m_y, &nChannels, 0);
if (!texture)
NFError("Texture failed to load from memory!");
glGenTextures(1, &m_id);
glBindTexture(GL_TEXTURE_2D, m_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, linear ? GL_RGBA : GL_SRGB_ALPHA, m_x, m_y, 0, nChannels == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, tex->data);
glTexImage2D(GL_TEXTURE_2D, 0, linear ? GL_RGBA : GL_SRGB_ALPHA, m_x, m_y, 0, nChannels == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, texture);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(texture);
m_isBase = tex->isBaseAsset;
tex->alreadyLoaded = true;
tex->loadedTexture = this;

View File

@ -160,33 +160,30 @@ namespace nf {
out.close();
}
std::string readFile(const std::string& filename, bool compressed) {
bool readFile(const std::string& filename, std::string& out, bool assetPack) {
if (!s_dHandle)
CreateDecompressor(COMPRESS_ALGORITHM_XPRESS_HUFF, NULL, &s_dHandle);
std::ifstream in;
in.open(filename, std::ios::binary);
if (!in)
NFError("File \"" + (std::string)filename + (std::string)"\" could not be read!");
return false;
std::stringstream ss;
ss << in.rdbuf();
std::string read(ss.str());
out = ss.str();
if (compressed) {
if (assetPack) {
size_t decompSize;
Decompress(s_dHandle, &read[0], read.size(), NULL, 0, &decompSize);
Decompress(s_dHandle, &out[0], out.size(), NULL, 0, &decompSize);
char* buff = new char[decompSize];
Decompress(s_dHandle, &read[0], read.size(), buff, decompSize, &decompSize);
read = std::string(buff, decompSize);
Decompress(s_dHandle, &out[0], out.size(), buff, decompSize, &decompSize);
out = std::string(buff, decompSize);
delete[] buff;
}
if (read.size() > 4 && read.substr(0, 4) == "NFEF") {
read = read.substr(4);
for (unsigned int i = 0; i < read.size(); i++)
read[i] = read[i] - 100;
for (unsigned int i = 0; i < out.size(); i++)
out[i] = out[i] - 100;
}
return read;
return true;
}
}

View File

@ -23,7 +23,7 @@ namespace nf {
struct AModel : Asset {
Model* loadedModel = nullptr;
std::unordered_map<std::string, ATexture*> neededTextures;
std::vector<ATexture*> neededTextures;
~AModel() override;
};

View File

@ -19,34 +19,18 @@ namespace nf {
~Model();
private:
struct TempMaterial {
std::vector<float> outVB;
std::vector<float> unindexedVB;
std::vector<unsigned int> vbIndices;
std::vector<float> outTC;
std::vector<float> unindexedTC;
std::vector<unsigned int> tcIndices;
std::vector<float> outVN;
std::vector<float> unindexedVN;
std::vector<unsigned int> vnIndices;
std::vector<float> unindexedTan;
std::vector<float> outTan;
std::vector<unsigned int> outIB;
unsigned int ibCount = 0;
std::string diffuseTextureName;
struct Material {
Texture* diffuse;
Texture* specular;
Texture* normal;
Vec3 diffuseColor;
std::string specularTextureName;
std::string normalTextureName;
float shininess = 1.0f;
};
void parseMaterials(std::unordered_map<std::string, TempMaterial*>& mats, std::vector<char>& mtl);
void createMaterials(const std::string& mats, AModel* model);
bool m_base;
std::vector<std::tuple<Texture*, Texture*, Texture*, float, float, float, float>> m_materials;
const char* m_newMtl;
const char* m_newLine;
std::vector<Material> m_materials;
const std::string m_hasDiffString = "hasDiffuseTex[";
const std::string m_diffString = "diffuseTexture[";
const std::string m_diffColorString = "diffuseColor[";

View File

@ -21,8 +21,8 @@ namespace nf {
void setActorVelocity(Entity* ent, const Vec3& vel);
void setActorMass(Entity* ent, float mass);
void update(float dt);
void addConvexMesh(Model* model, std::vector<float>& vertices);
void addTriangleMesh(Model* model, std::vector<float>& vertices, std::vector<unsigned int>& indices);
void addConvexMesh(Model* model, const float* vertices, unsigned int buffSize);
void addTriangleMesh(Model* model, const float* vertices, unsigned int vertBuffSize, const unsigned int* indices, unsigned int indicesCount);
void addActor(Entity* entity);
void closeScene();

View File

@ -428,13 +428,12 @@ std::exit(-1);}
/**
* @brief Reads a file's bytes into an std::string
* @param filename Path and name of file to be read, including extensions; Relative or absolute
* @param compressed Internal use only as of now
* @return An std::string containing the specified file's bytes
* @param out The output std::string to receive the file contents
* @param assetPack Internal use only as of now
* @return If the file was successfully read or not
*
* This function automatically detects whether or not the target file is encrypted
* and decrypts it if it is.
*
* @todo If files aren't found, the engine errors. Change this.
*/
std::string readFile(const std::string& filename, bool compressed = false);
bool readFile(const std::string& filename, std::string& out, bool assetPack = false);
}