Finished reworking asset builder; Models are now cooked when built
This commit is contained in:
parent
cc0316ff80
commit
7a93befa14
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
void cookTexture(const std::string& in, std::string& out);
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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[";
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
Reference in New Issue
Block a user