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
	 Grayson Riffe (Laptop)
						Grayson Riffe (Laptop)