Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9183f05459 | ||
![]() |
f2bd6e457a | ||
![]() |
a85f77c023 | ||
![]() |
f691da4103 |
@ -5,6 +5,10 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="ProdDebug|x64">
|
||||
<Configuration>ProdDebug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
@ -24,6 +28,12 @@
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
@ -39,6 +49,9 @@
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
@ -48,6 +61,11 @@
|
||||
<OutDir>$(ProjectDir)bin\$(Platform)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)int\$(Platform)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'">
|
||||
<OutDir>$(ProjectDir)bin\$(Platform)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)int\$(Platform)$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(ProjectDir)bin\$(Platform)$(Configuration)\</OutDir>
|
||||
@ -57,7 +75,7 @@
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NFDEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(SolutionDir)NothinFancy\src\include\</AdditionalIncludeDirectories>
|
||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||
@ -78,6 +96,37 @@ if exist "$(OutDir)assets" (rmdir "$(OutDir)assets" /S /Q && goto end) e
|
||||
mkdir "$(OutDir)assets"
|
||||
move "*.nfpack" "$(OutDir)assets\"
|
||||
cd "$(SolutionDir)NothinFancy\assets"
|
||||
if exist "base.nfpack" (copy "base.nfpack" "$(OutDir)assets\")</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NFDEBUG;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(SolutionDir)NothinFancy\src\include\</AdditionalIncludeDirectories>
|
||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>
|
||||
<IgnoreSpecificDefaultLibraries>libcmt.lib</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>cd assets
|
||||
"$(SolutionDir)NFAssetBuilder\bin\x64Release\NFAssetBuilder.exe"
|
||||
if exist "$(OutDir)assets" (rmdir "$(OutDir)assets" /S /Q && goto end) else goto end
|
||||
:end
|
||||
mkdir "$(OutDir)assets"
|
||||
move "*.nfpack" "$(OutDir)assets\"
|
||||
cd "$(SolutionDir)NothinFancy\assets"
|
||||
if exist "base.nfpack" (copy "base.nfpack" "$(OutDir)assets\")</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
|
@ -7,6 +7,10 @@
|
||||
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'">
|
||||
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
|
@ -7,11 +7,9 @@
|
||||
#include <set>
|
||||
|
||||
void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
|
||||
std::vector<char> obj(&OBJin[0], &OBJin[0] + OBJin.size());
|
||||
std::vector<char> mtl(&MTLin[0], &MTLin[0] + MTLin.size());
|
||||
|
||||
std::unordered_map<std::string, TempMaterial*> mats;
|
||||
parseMaterials(mats, mtl);
|
||||
parseMaterials(mats, MTLin);
|
||||
|
||||
std::vector<float> vbRaw, tcRaw, vnRaw;
|
||||
std::string usingMat;
|
||||
@ -19,19 +17,16 @@ void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
|
||||
bool tcPresent = false, vnPresent = false;
|
||||
size_t position = 0;
|
||||
|
||||
while (true) {
|
||||
size_t nextLine = std::search(obj.begin() + position, obj.end(), "\n", "\n" + std::strlen("\n")) - (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::stringstream ss(OBJin);
|
||||
std::string line;
|
||||
while (std::getline(ss, line)) {
|
||||
std::stringstream ss2(line);
|
||||
std::string firstWord;
|
||||
ss >> firstWord;
|
||||
ss2 >> firstWord;
|
||||
|
||||
if (std::strcmp(&firstWord[0], "v") == 0) {
|
||||
float x = 0.0f, y = 0.0f, z = 0.0f;
|
||||
ss >> x >> y >> z;
|
||||
ss2 >> x >> y >> z;
|
||||
vbRaw.push_back(x);
|
||||
vbRaw.push_back(y);
|
||||
vbRaw.push_back(z);
|
||||
@ -39,21 +34,21 @@ void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
|
||||
else if (std::strcmp(&firstWord[0], "vt") == 0) {
|
||||
tcPresent = true;
|
||||
float u = 0.0f, v = 0.0f;
|
||||
ss >> u >> v;
|
||||
ss2 >> 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;
|
||||
ss2 >> 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;
|
||||
ss2 >> matName;
|
||||
usingMat = matName;
|
||||
}
|
||||
else if (std::strcmp(&firstWord[0], "f") == 0) {
|
||||
@ -64,8 +59,8 @@ void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
|
||||
|
||||
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)
|
||||
ss2 >> 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 (ss2.rdbuf()->in_avail() > 1)
|
||||
Error("Model has non-triangle faces!");
|
||||
mats[usingMat]->vbIndices.push_back(vertexIndex[0]);
|
||||
mats[usingMat]->vbIndices.push_back(vertexIndex[1]);
|
||||
@ -262,43 +257,41 @@ void cookModel(std::string& OBJin, std::string& MTLin, std::string& out) {
|
||||
out.append((char*)vboIndices.data(), indicesSize);
|
||||
}
|
||||
|
||||
void parseMaterials(std::unordered_map<std::string, TempMaterial*>& mats, std::vector<char>& mtl) {
|
||||
void parseMaterials(std::unordered_map<std::string, TempMaterial*>& mats, std::string& mtl) {
|
||||
std::string currMat;
|
||||
size_t position = 0;
|
||||
while (true) {
|
||||
size_t nextLine = std::search(mtl.begin() + position, mtl.end(), "\n", "\n" + std::strlen("\n")) - (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::stringstream ss(mtl);
|
||||
std::string line;
|
||||
while (std::getline(ss, line)) {
|
||||
std::stringstream ss2(line);
|
||||
std::string firstWord;
|
||||
ss >> firstWord;
|
||||
ss2 >> firstWord;
|
||||
|
||||
if (std::strcmp(&firstWord[0], "newmtl") == 0) {
|
||||
ss >> currMat;
|
||||
ss2 >> currMat;
|
||||
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;
|
||||
ss2 >> r >> g >> b;
|
||||
mats[currMat]->diffuseColor = Vec3(r, g, b);
|
||||
}
|
||||
else if (std::strcmp(&firstWord[0], "map_Kd") == 0) {
|
||||
std::string texName = getNewLine(ss);
|
||||
std::string texName = getTextureName(ss2);
|
||||
mats[currMat]->diffuseTextureName = texName;
|
||||
}
|
||||
else if (std::strcmp(&firstWord[0], "map_Ks") == 0) {
|
||||
std::string texName = getNewLine(ss);
|
||||
std::string texName = getTextureName(ss2);
|
||||
mats[currMat]->specularTextureName = texName;
|
||||
}
|
||||
else if (std::strcmp(&firstWord[0], "map_Bump") == 0) {
|
||||
std::string texName = getNewLine(ss);
|
||||
std::string texName = getTextureName(ss2);
|
||||
mats[currMat]->normalTextureName = texName;
|
||||
}
|
||||
else if (std::strcmp(&firstWord[0], "Ns") == 0) {
|
||||
float s = 0.0f;
|
||||
ss >> s;
|
||||
ss2 >> s;
|
||||
mats[currMat]->shininess = s;
|
||||
}
|
||||
}
|
||||
@ -331,3 +324,11 @@ std::vector<std::string> getNeededTextures(std::string mtl) {
|
||||
out.push_back(curr);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string getTextureName(std::stringstream& ss) {
|
||||
std::string out;
|
||||
std::getline(ss, out);
|
||||
out = out.substr(out.find_last_of("\\/") + 1);
|
||||
|
||||
return out;
|
||||
}
|
@ -27,5 +27,6 @@ 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 parseMaterials(std::unordered_map<std::string, TempMaterial*>& mats, std::string& mtl);
|
||||
std::vector<std::string> getNeededTextures(std::string mtl);
|
||||
std::string getTextureName(std::stringstream& ss);
|
@ -5,6 +5,10 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="ProdDebug|x64">
|
||||
<Configuration>ProdDebug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
@ -31,6 +35,13 @@
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
@ -42,6 +53,9 @@
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
@ -53,11 +67,16 @@
|
||||
<OutDir>$(ProjectDir)bin\$(Platform)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)int\$(Platform)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(ProjectDir)bin\$(Platform)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)int\$(Platform)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>GLEW_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NFDEBUG;GLEW_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(ProjectDir)dep\include\</AdditionalIncludeDirectories>
|
||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||
@ -116,6 +135,43 @@
|
||||
<PostBuildEvent />
|
||||
<PostBuildEvent>
|
||||
<Command>cd assets
|
||||
"$(SolutionDir)NFAssetBuilder\bin\x64Release\NFAssetBuilder.exe"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ProdDebug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NFDEBUG;GLEW_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(ProjectDir)dep\include\</AdditionalIncludeDirectories>
|
||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>glew32s.lib;opengl32.lib;freetype.lib;xaudio2.lib;Cabinet.lib;libogg.lib;libvorbis.lib;libvorbisfile.lib;PhysXFoundation.lib;PhysXCommon.lib;PhysX.lib;PhysXCooking.lib;PhysXExtensions.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)dep\lib\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4006 %(AdditionalOptions)</AdditionalOptions>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
<ProjectReference>
|
||||
<LinkLibraryDependencies>true</LinkLibraryDependencies>
|
||||
</ProjectReference>
|
||||
<PostBuildEvent />
|
||||
<PostBuildEvent>
|
||||
<Command>cd assets
|
||||
"$(SolutionDir)NFAssetBuilder\bin\x64Release\NFAssetBuilder.exe"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
|
@ -80,7 +80,7 @@ namespace nf {
|
||||
|
||||
void Application::run() {
|
||||
NFLog("Running application...");
|
||||
#ifdef _DEBUG
|
||||
#ifdef NFDEBUG
|
||||
Debug::startTimer();
|
||||
SetThreadDescription(GetCurrentThread(), L"Input Thread");
|
||||
SetConsoleTitle(toWide("Nothin' Fancy v" + (std::string)NFVERSION).data());
|
||||
@ -115,9 +115,10 @@ namespace nf {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
mainThread.join();
|
||||
#ifdef _DEBUG
|
||||
#ifdef NFDEBUG
|
||||
Debug::stopTimer();
|
||||
#endif
|
||||
NFLog("Exited application");
|
||||
}
|
||||
|
||||
bool Application::hasCustomWindowIcon() {
|
||||
@ -312,7 +313,7 @@ namespace nf {
|
||||
}
|
||||
|
||||
void Application::runMainGameThread() {
|
||||
#ifdef _DEBUG
|
||||
#ifdef NFDEBUG
|
||||
SetThreadDescription(GetCurrentThread(), L"Main Engine Thread");
|
||||
#endif
|
||||
m_renderer = new Renderer(this);
|
||||
@ -339,14 +340,8 @@ namespace nf {
|
||||
|
||||
m_fpsClock2 = std::chrono::steady_clock::now();
|
||||
m_fpsDuration = m_fpsClock2 - m_fpsClock1;
|
||||
if (m_fpsDuration.count() >= 0.2) {
|
||||
if (m_fpsDuration.count() >= 0.1) {
|
||||
m_FPS = (int)std::round(1.0 / m_deltaTime);
|
||||
#ifdef _DEBUG
|
||||
static int i = 0;
|
||||
i++;
|
||||
if (i % 5 == 0)
|
||||
NFLog("FPS: " + std::to_string(m_FPS));
|
||||
#endif
|
||||
m_fpsClock1 = std::chrono::steady_clock::now();
|
||||
}
|
||||
}
|
||||
@ -452,7 +447,6 @@ namespace nf {
|
||||
break;
|
||||
}
|
||||
case WM_CLOSE: {
|
||||
NFLog("Exiting NF application");
|
||||
DestroyWindow(hWnd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace nf {
|
||||
}
|
||||
|
||||
void AudioEngine::runAudioThread() {
|
||||
#ifdef _DEBUG
|
||||
#ifdef NFDEBUG
|
||||
SetThreadDescription(GetCurrentThread(), L"Audio Thread");
|
||||
#endif
|
||||
//Wait to initialize stuff until the master voice is created if it hasn't been already
|
||||
|
@ -7,7 +7,7 @@
|
||||
namespace nf {
|
||||
class PhysicsErrorCallback : public PxErrorCallback {
|
||||
virtual void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line) {
|
||||
#ifdef _DEBUG
|
||||
#ifdef NFDEBUG
|
||||
Debug::ErrorImp(message, file, line);
|
||||
__debugbreak();
|
||||
#else
|
||||
|
@ -16,8 +16,10 @@ namespace nf {
|
||||
|
||||
static const float deg2rad = (float)M_PI / 180.0f;
|
||||
|
||||
#ifdef _DEBUG
|
||||
NFDEBUGINIT;
|
||||
#ifdef NFDEBUG
|
||||
std::chrono::steady_clock::time_point Debug::m_initTime = std::chrono::high_resolution_clock::now();
|
||||
bool Debug::m_timerStarted = false;
|
||||
static HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
void Debug::startTimer() {
|
||||
m_timerStarted = true;
|
||||
@ -31,45 +33,34 @@ namespace nf {
|
||||
void Debug::LogImp(const char* in) {
|
||||
if(m_timerStarted)
|
||||
printCurrentTime();
|
||||
std::printf("NF Log: %s\n", in);
|
||||
std::printf("NF ");
|
||||
SetConsoleTextAttribute(cmd, 6);
|
||||
std::printf("Log");
|
||||
SetConsoleTextAttribute(cmd, 7);
|
||||
std::printf(": %s\n", in);
|
||||
}
|
||||
|
||||
void Debug::LogImp(const std::string& in) {
|
||||
if (m_timerStarted)
|
||||
printCurrentTime();
|
||||
std::printf("NF Log: ");
|
||||
std::cout << in << "\n";
|
||||
LogImp(in.c_str());
|
||||
}
|
||||
|
||||
void Debug::LogImp(int in) {
|
||||
if (m_timerStarted)
|
||||
printCurrentTime();
|
||||
std::printf("NF Log: %i\n", in);
|
||||
LogImp(std::to_string(in));
|
||||
}
|
||||
|
||||
void Debug::LogImp(float in) {
|
||||
if (m_timerStarted)
|
||||
printCurrentTime();
|
||||
std::printf("NF Log: %.4f\n", in);
|
||||
LogImp(std::to_string(in));
|
||||
}
|
||||
//TODO: Test every Error in release mode
|
||||
void Debug::ErrorImp(const char* in, const char* filename, int line) {
|
||||
if (m_timerStarted)
|
||||
printCurrentTime();
|
||||
static HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(cmd, FOREGROUND_RED);
|
||||
std::printf("NF Error (%s, %i): %s\n", filename, line, in);
|
||||
SetConsoleTextAttribute(cmd, 7);
|
||||
}
|
||||
|
||||
void Debug::ErrorImp(const std::string& in, const char* filename, int line) {
|
||||
if (m_timerStarted)
|
||||
printCurrentTime();
|
||||
static HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(cmd, FOREGROUND_RED);
|
||||
std::printf("NF Error (%s, %i): ", filename, line);
|
||||
std::cout << in << "\n";
|
||||
SetConsoleTextAttribute(cmd, 7);
|
||||
ErrorImp(in.c_str(), filename, line);
|
||||
}
|
||||
|
||||
void Debug::printCurrentTime() {
|
||||
@ -91,7 +82,7 @@ namespace nf {
|
||||
if (!m_loading)
|
||||
NFLog("\"" + m_funcName + (std::string)"\" took " + std::to_string(dur.count() * 1000.0f) + (std::string)" ms.");
|
||||
else
|
||||
NFLog("Loading took " + std::to_string(dur.count()) + (std::string)" seconds.");
|
||||
NFLog("Loading state took " + std::to_string(dur.count()) + (std::string)" seconds.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace nf {
|
||||
* A cubemap is a cube with a texture on each one of its 6 sides.
|
||||
*
|
||||
* @sa @ref createCubemapTut
|
||||
* @ref customCubemap
|
||||
* @ref customCubemaps
|
||||
*/
|
||||
class Cubemap : public Drawable, public NFObject {
|
||||
public:
|
||||
|
@ -21,12 +21,9 @@ namespace nf {
|
||||
* Current version of the engine in the format major.minor.patch
|
||||
*/
|
||||
#define NFVERSION "0.5.0"
|
||||
#if defined(_DEBUG) || defined(doxygen)
|
||||
#if defined(NFDEBUG) || defined(doxygen)
|
||||
//Strips __FILE__ down to only the name of the file
|
||||
#define __FILENAME__ strrchr(__FILE__, '\\') + 1
|
||||
//Initializes static variables needed for debugging
|
||||
#define NFDEBUGINIT std::chrono::steady_clock::time_point Debug::m_initTime = std::chrono::high_resolution_clock::now(); \
|
||||
bool Debug::m_timerStarted = false
|
||||
/**
|
||||
* @defgroup macros Macros
|
||||
*
|
||||
@ -113,7 +110,7 @@ __debugbreak();}
|
||||
#define NFSleepS(x)
|
||||
#define NFSleepMS(x)
|
||||
#define NFLog(x)
|
||||
#define NFError(x) {MessageBox(FindWindow(L"NFClass", NULL), toWide(x).data(), L"NF Engine Error", MB_OK | MB_ICONERROR);\
|
||||
#define NFError(x) {MessageBox(FindWindow(L"NFClass", NULL), nf::toWide(x).data(), L"NF Engine Error", MB_OK | MB_ICONERROR);\
|
||||
std::exit(-1);}
|
||||
#define NFTimeFunc
|
||||
#define NFTimerLoad
|
||||
@ -414,9 +411,9 @@ std::exit(-1);}
|
||||
float w;
|
||||
};
|
||||
|
||||
#ifndef NFIMPL
|
||||
const std::wstring toWide(const char* in);
|
||||
const std::wstring toWide(const std::string& in);
|
||||
#ifndef NFIMPL
|
||||
Vec4 degToQuat(const Vec3& in);
|
||||
#endif
|
||||
|
||||
|
@ -15,19 +15,26 @@ EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
ProdDebug|x64 = ProdDebug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1B9C5361-E301-41BF-97E7-56D65F11E2BB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1B9C5361-E301-41BF-97E7-56D65F11E2BB}.Debug|x64.Build.0 = Debug|x64
|
||||
{1B9C5361-E301-41BF-97E7-56D65F11E2BB}.ProdDebug|x64.ActiveCfg = ProdDebug|x64
|
||||
{1B9C5361-E301-41BF-97E7-56D65F11E2BB}.ProdDebug|x64.Build.0 = ProdDebug|x64
|
||||
{1B9C5361-E301-41BF-97E7-56D65F11E2BB}.Release|x64.ActiveCfg = Release|x64
|
||||
{1B9C5361-E301-41BF-97E7-56D65F11E2BB}.Release|x64.Build.0 = Release|x64
|
||||
{B7FEC2D6-1D8F-487E-89CB-FD611FD1AEB6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B7FEC2D6-1D8F-487E-89CB-FD611FD1AEB6}.Debug|x64.Build.0 = Debug|x64
|
||||
{B7FEC2D6-1D8F-487E-89CB-FD611FD1AEB6}.ProdDebug|x64.ActiveCfg = ProdDebug|x64
|
||||
{B7FEC2D6-1D8F-487E-89CB-FD611FD1AEB6}.ProdDebug|x64.Build.0 = ProdDebug|x64
|
||||
{B7FEC2D6-1D8F-487E-89CB-FD611FD1AEB6}.Release|x64.ActiveCfg = Release|x64
|
||||
{B7FEC2D6-1D8F-487E-89CB-FD611FD1AEB6}.Release|x64.Build.0 = Release|x64
|
||||
{771B4AEE-E2C6-4745-AC40-1EF57149612E}.Debug|x64.ActiveCfg = Release|x64
|
||||
{771B4AEE-E2C6-4745-AC40-1EF57149612E}.Debug|x64.Build.0 = Release|x64
|
||||
{771B4AEE-E2C6-4745-AC40-1EF57149612E}.ProdDebug|x64.ActiveCfg = Release|x64
|
||||
{771B4AEE-E2C6-4745-AC40-1EF57149612E}.ProdDebug|x64.Build.0 = Release|x64
|
||||
{771B4AEE-E2C6-4745-AC40-1EF57149612E}.Release|x64.ActiveCfg = Release|x64
|
||||
{771B4AEE-E2C6-4745-AC40-1EF57149612E}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
|
@ -169,7 +169,7 @@ HTML_HEADER = header.html
|
||||
HTML_FOOTER = footer.html
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET = theme.css
|
||||
HTML_EXTRA_FILES = images/favicon.png
|
||||
HTML_EXTRA_FILES = images/favicon.png videos/buttondemo.mp4
|
||||
HTML_COLORSTYLE_HUE = 30
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 70 KiB |
BIN
docs/images/blanktemplate.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
docs/images/customfont.png
Normal file
After Width: | Height: | Size: 236 KiB |
BIN
docs/images/custommodel.png
Normal file
After Width: | Height: | Size: 618 KiB |
BIN
docs/images/examplebuttonhover.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
docs/images/examplebuttonidle.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
docs/images/examplebuttonpressed.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
docs/images/exportsettings.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
docs/images/modeltut1.png
Normal file
After Width: | Height: | Size: 519 KiB |
BIN
docs/images/modeltut2.png
Normal file
After Width: | Height: | Size: 572 KiB |
BIN
docs/images/modeltut3.png
Normal file
After Width: | Height: | Size: 544 KiB |
BIN
docs/images/ui.png
Normal file
After Width: | Height: | Size: 645 KiB |
@ -15,15 +15,15 @@ In order to develop an NF application, you must first have the following:
|
||||
|
||||
The current version of the engine can be downloaded [here](http://graysonriffe.com/nf/nf.zip).
|
||||
|
||||
@note Windows Security may first need to scan some of the included binaries and your
|
||||
build output before they can be run. You should never get a message from Windows Security
|
||||
@note Your antivirus may first need to scan some of the included binaries and your
|
||||
build output before they can be run. You should never get a message from any antivirus
|
||||
that a virus has been found in any of these files.
|
||||
|
||||
Inside the zip file, you will find:
|
||||
|
||||
- **example** - The example app complete with the source and a build
|
||||
- **manual** - An offline version of this manual
|
||||
- **index.html** - The homepage
|
||||
- **index.html** - The main page
|
||||
- **redist** - MSVC Redistributable (See @ref packagingTut)
|
||||
- **template** - A template MSVC project already setup to work with the engine
|
||||
|
||||
@ -44,20 +44,19 @@ project (`NFApp` by default), can be renamed at any time.
|
||||
|
||||
@note The template project is setup to build *Debug* and *Release* configurations. The *Debug*
|
||||
configuration includes a console window with debug output. The *Release* configuration does
|
||||
not have this console window. By default, the current configuration can be changed in the
|
||||
top toolbar.
|
||||
not have this console window, and will run as fast as possible with maximum optimizations.
|
||||
By default, the current configuration can be changed in the top toolbar.
|
||||
|
||||
Once the solution has been opened, you can find the `main.cpp` file inside the `src` folder
|
||||
as shown below.
|
||||
Once the solution has been opened, you can find the `main.cpp` file inside the `src` folder:
|
||||
|
||||
@image html blankproject.png "The template opened in Visual Studio" width=70%
|
||||
@image html blanktemplate.png "The template opened in Visual Studio" width=70%
|
||||
|
||||
To build the project, go to Build -> Build Solution or Build Project, which will not build
|
||||
To build the project, go to Build -> Build Solution or Build Project. The latter will not build
|
||||
your assets. You can also also hit the default keyboard shortcut of `Ctrl-Shift-B` to build
|
||||
both your app and assets at once.
|
||||
both your app and assets.
|
||||
|
||||
@note When the "Build Assets" project is built, the resulting NFPacks are moved to
|
||||
the output `assets` directory next to your .exe for you.
|
||||
the output `assets` directory next to your `.exe` for you.
|
||||
|
||||
NF is a **statically-linked** library. This means that your build will not
|
||||
rely on any external dlls other than the MSVC redistributable.
|
||||
rely on any external dlls other than the MSVC redistributable. See @ref packagingTut.
|
@ -15,12 +15,14 @@ main thread of an NF app might be typically doing in the program's lifetime.
|
||||
|
||||
@image html applifetime.png "The lifetime of a typical NF app" width=20%
|
||||
|
||||
Using the engine's architecture, you might not even write any functions that are called
|
||||
Using this architecture, you might not even write any functions that are called
|
||||
from `main`. Most of the code that programs the engine's behavior should be called in
|
||||
your state's [update function](@ref nf::Gamestate::update).
|
||||
|
||||
To allow a translate unit to use the engine, you must include `NothinFancy.h`. This
|
||||
header contains every class and function.
|
||||
header contains every class and function you will need.
|
||||
|
||||
---
|
||||
|
||||
@section createConfigTut Creating a Config
|
||||
|
||||
@ -29,9 +31,8 @@ engine should display on the screen. nf::Config has these fields:
|
||||
|
||||
- `width` - The width of the window if `fullscreen` is set to `false`
|
||||
- `height` - The height of the window if `fullscreen` is set to `false`
|
||||
- `fullscreen` - `true` sets the display to the size of the monitor the app is
|
||||
- `fullscreen` - `true` sets the display to the size of the monitor the app is opened on
|
||||
- `title` - The title of the window shown on the caption bar and taskbar
|
||||
opened on
|
||||
|
||||
To create a 1280 by 720 window with a title of "NF Example", you would write:
|
||||
|
||||
@ -52,7 +53,7 @@ We then pass this config to an nf::Application
|
||||
@section createAppTut Creating and Configuring an Application
|
||||
|
||||
The nf::Application class represents an instance of the engine. This is the point where
|
||||
you will attach your states and run the engine.
|
||||
you will attach your states and run your application.
|
||||
|
||||
@note In a program and on a single machine, there can only be one single instance of
|
||||
this class at a time. Attempting to create mulitple will result in an error.
|
||||
@ -64,7 +65,7 @@ nf::Application app(conf);
|
||||
~~~
|
||||
|
||||
Constructing an application doesn't do much. It merely allows you to access the member
|
||||
functions to setup your application.
|
||||
functions to setup your application and run it later.
|
||||
|
||||
Here are some functions you might want to call at this point:
|
||||
|
||||
@ -86,7 +87,7 @@ Once these functions have been called, the app can be run:
|
||||
|
||||
~~~cpp
|
||||
CustomGamestate* customState = new CustomGamestate; //Inherits nf::Gamestate
|
||||
app.addState(customState, "State 1"); //"State One" is this state's identifier.
|
||||
app.addState(customState, "State 1"); //"State 1" is this state's identifier.
|
||||
app.setDefaultState("State 1"); //Will error without this
|
||||
app.run(); //Blocks until exit
|
||||
~~~
|
||||
@ -336,12 +337,104 @@ After rendering, our world will have a background.
|
||||
@section customAssetsTut Adding Your Assets
|
||||
|
||||
NF's asset system builds your assets into NFPacks that the engine reads at runtime. The
|
||||
external tool `NFAssetCreator.exe` creates these for you. For a complete guide, please
|
||||
see @ref assets.
|
||||
external tool `NFAssetBuilder.exe` creates these for you. You can then access these packs
|
||||
through the nf::AssetPack class. For a complete guide, please see @ref assets.
|
||||
|
||||
@image html custommodel.png "An example of a custom model" width=50%
|
||||
|
||||
@section createUITut Creating a UI
|
||||
|
||||
@todo Lighting page?
|
||||
NF currently has three classes of UI objects:
|
||||
|
||||
- nf::Text - A string of text on the screen
|
||||
- nf::UITexture - Any 2D texture to put on the screen
|
||||
- nf::Button - A horizontal button that can be clicked with the mouse
|
||||
|
||||
To create a text:
|
||||
|
||||
~~~cpp
|
||||
text.create("NF Test", nf::Vec2(0.8, 0.1));
|
||||
text.setScale(2.0);
|
||||
std::string string = "More Text";
|
||||
text.setText(string);
|
||||
~~~
|
||||
|
||||
@note The default font is Microsoft's Segoe UI Light, but a text's font
|
||||
[can be changed](@ref customFonts).
|
||||
|
||||
To create a texture on the UI:
|
||||
|
||||
~~~cpp
|
||||
texture.create(nf::BaseAssets::logo, nf::Vec2(0.1, 0.1));
|
||||
~~~
|
||||
|
||||
To create a clickable button:
|
||||
|
||||
~~~cpp
|
||||
button.create(nf::Vec2(0.1, 0.1), "Text on button");
|
||||
|
||||
//You can also center any of these three classes by calling
|
||||
button.centered(true, false);
|
||||
//where the first bool is the x-axis and the second is the y-axis
|
||||
~~~
|
||||
|
||||
The default button textures [can also be changed](@ref customButtons).
|
||||
|
||||
Since buttons are controlled by the mouse, they cannot be interacted with in our current
|
||||
camera mode. Let's add a keybind that will switch between the appropriate modes.
|
||||
|
||||
~~~cpp
|
||||
//In our update function...
|
||||
if (app->isKeyPressed(NFI_E))
|
||||
camera->setType(camera->getType() == nf::Camera::Type::UI ? nf::Camera::Type::FIRST_PERSON : nf::Camera::Type::UI);
|
||||
|
||||
if (button.isClicked()) {
|
||||
NFLog("Clicked!);
|
||||
}
|
||||
~~~
|
||||
|
||||
@image html ui.png "Our new UI with a working button" width=70%
|
||||
|
||||
@section soundTut Adding Sound
|
||||
|
||||
Our app is silent as of now. To play a sound, create an nf::Sound object and call its
|
||||
[play](@ref nf::Sound::play) function. Creating a sound requires a custom asset to be
|
||||
loaded. See the [assets page](@ref customSounds).
|
||||
|
||||
NF supports 3D sound.
|
||||
|
||||
~~~cpp
|
||||
sound.create(pack.get("Sound.ogg"));
|
||||
|
||||
//In update somewhere...
|
||||
sound.play();
|
||||
~~~
|
||||
|
||||
If a sound is played like this (with no position set), it will sound as if it is coming from
|
||||
every direction. But if we set the position of the sound, it will sound as if it originates
|
||||
from that position. This can either be done by setting a static position in the world,
|
||||
or by specifying an existing nf::Entity, which will cause the sound to always play at that
|
||||
entity's origin (probably inside the model).
|
||||
|
||||
~~~cpp
|
||||
//Play at a static position:
|
||||
sound.setPosition(nf::Vec3(10.0, 25.0, 15.0));
|
||||
|
||||
//Play dynamically wherever the target entity is:
|
||||
sound.setEntity(entity2);
|
||||
~~~
|
||||
|
||||
@section gamestateSwitchTut Switching Gamestates
|
||||
|
||||
To unload the current state and load another state, call:
|
||||
|
||||
~~~cpp
|
||||
app->changeState("State 2"); //String identifier we defined earlier
|
||||
~~~
|
||||
|
||||
@note The currently running state that calls [changeState](@ref nf::Application::changeState)
|
||||
does not stop running right away. The `update` and `render` functions of that state are called
|
||||
until the loading screen fades in completely.
|
||||
|
||||
@section debuggingTut Debugging Your App
|
||||
|
||||
@ -368,5 +461,6 @@ Other than that, a build can be very simple:
|
||||
- **NFApp.exe** - The application binary which is named from the MSVC project
|
||||
- **assets** - The folder which holds your NFPacks
|
||||
- **base.nfpack** - The NFPack that holds both critical and default assets
|
||||
- **Your Assets** - The rest of the NFPacks your application needs
|
||||
|
||||
These are the only files you need to package in your build.
|
@ -1,14 +1,181 @@
|
||||
@page assets Asset System
|
||||
@tableofcontents
|
||||
|
||||
This page details NF's asset system and custom NFPack format.
|
||||
This page details NF's asset system and how to work with it.
|
||||
|
||||
The following table shows the currently supported file types that the asset builder
|
||||
will accept.
|
||||
|
||||
Asset Type | Supported File Type(s)
|
||||
-|-
|
||||
Model | Wavefront `.obj` / `.mtl`
|
||||
Font | TrueType `.ttf`
|
||||
Texture (Models, UI, Buttons, Cubemaps) | `.png` or `.jpg`
|
||||
Audio | `.wav` or Ogg Vorbis `.ogg`
|
||||
|
||||
@section buildAssets How to Build Your Assets
|
||||
|
||||
@todo Asset system page
|
||||
This is the basic workflow when working with assets:
|
||||
|
||||
@section customFonts Custom Font Assets
|
||||
1. Create a folder in your project's `asset` folder. The name of the folder will be the
|
||||
name of the output pack in the form `foldername.nfpack`.
|
||||
2. Place your assets anywhere inside this folder, including in any subfolders.
|
||||
3. Build the packs by either building the "Build Assets" project in the template or by
|
||||
manually running `NFAssetBuilder.exe` by clicking on it. If you choose this method, you
|
||||
must also manually copy the needed packs to your app's `assets` directory.
|
||||
4. In your code, create an nf::AssetPack object and call the [load](@ref nf::AssetPack::load)
|
||||
function while passing in the name of the pack, including the extension.
|
||||
5. Call the [get](@ref nf::AssetPack::get) function with the name of the asset file
|
||||
to retrieve an Asset pointer to use in various `create` functions.
|
||||
|
||||
@section customButtons Custom Button Assets
|
||||
---
|
||||
|
||||
@section customCubemap Custom Cubemap Assets
|
||||
@section customModels Models
|
||||
|
||||
To import a custom model into NF, it must first meet some requirements:
|
||||
|
||||
- Format must be a Wavefront `.obj` file
|
||||
- The model must include both texture coordinate and normal data
|
||||
- All faces must be triangles
|
||||
- There must exist a `.mtl` file with the same name as the `.obj` file somewhere in the
|
||||
pack folder that contains material information
|
||||
|
||||
Using Blender can fill all of these requirements easily. This tutorial uses Blender v3.0.0.
|
||||
|
||||
Let's say I have this teapot I want to place in a scene:
|
||||
|
||||
@image html modeltut1.png "My starting model" width=50%
|
||||
|
||||
It has enough detail already, but I want it to look smooth, so I'll make sure smooth
|
||||
shading is turned on for this object. This makes every part of the model smooth, but I
|
||||
don't want that on the handle of the lid. I want to see an edge there. The solution here
|
||||
is to turn on Object Data -> Normals -> "Auto Smooth" in the properties editor
|
||||
and adjust the degree threshold until I get what I want.
|
||||
|
||||
This should be the result:
|
||||
|
||||
@image html modeltut2.png "Our smooth model with a few sharp edges" width=50%
|
||||
|
||||
Now that that's done, I want to create the material this teapot will have. I want to
|
||||
apply a texture, so I'm going to unwrap the model and texture it. Blender materials
|
||||
translate directly into NF materials, so feel free to add multiple materials on the same
|
||||
model that use different textures.
|
||||
|
||||
To add a color texture to a material, direct an "Image Texture" to the "Base Color"
|
||||
input of the default Principled BSDF. This can either be done through the properties editor
|
||||
or node editor.
|
||||
|
||||
@todo Talk about specular and normal maps
|
||||
|
||||
@image html modeltut3.png "Our textured model" width=50%
|
||||
|
||||
I am now ready to export this model, so first make sure your model is selected, then
|
||||
go to File -> Export -> Wavefront (.obj). This will bring up another window where we will
|
||||
set some important options.
|
||||
|
||||
Under the "Geometry" heading, make sure these are checked. The model will not import into
|
||||
the engine unless all of these are checked.
|
||||
|
||||
@image html exportsettings.png "Important Export Settings" width=10%
|
||||
|
||||
Now that we have a pair of `.obj` and `.mtl` files, we can move them into our pack folder.
|
||||
Back in the code, once we have a loaded nf::AssetPack, we can create an entity with our
|
||||
new model like so:
|
||||
|
||||
~~~cpp
|
||||
//ap is the nf::AssetPack that has our NFPack loaded
|
||||
entity2.create(ap.get("teapot.obj"), nf::Vec3(0.0)); //Reference asset by name, including extension
|
||||
~~~
|
||||
|
||||
Lastly, don't forget to build your assets before running.
|
||||
|
||||
Used in the tutorial app, our model looks like this:
|
||||
|
||||
@image html custommodel.png "Our teapot in the engine" width=50%
|
||||
|
||||
---
|
||||
|
||||
@section customFonts Fonts
|
||||
|
||||
Custom fonts can be implemented very easily. All you need to do is include a TrueType
|
||||
`.ttf` font in your assets and reference it when you create texts:
|
||||
|
||||
~~~cpp
|
||||
text.create("Cool Font", nf::Vec2(0.1, 0.2), nf::Vec3(1.0f), 1.0f, 1.0f, ap.get("font.ttf"));
|
||||
~~~
|
||||
|
||||
@image html customfont.png "A text using the font \"Corsiva\"" width=30%
|
||||
|
||||
---
|
||||
|
||||
@section customButtons Button Textures
|
||||
|
||||
The default button textures can be overridden by adding textures with certain names
|
||||
to your assets where "name" can be anything you choose as an identifier.
|
||||
|
||||
- **name_buttonidle** - The texture that shows when the button is idle
|
||||
- **name_buttonhover** - The texture that shows when the mouse hovers over the button
|
||||
- **name_buttonpressed** - The texture that shows when the button clicked
|
||||
|
||||
These images can be of any accepted image format. They should all have the same dimensions.
|
||||
|
||||
@warning If a button texture set is incomplete, the engine will error when it reads the
|
||||
NFPack.
|
||||
|
||||
Once the textures are in place, they can be accessed in your nf::AssetPack like
|
||||
this:
|
||||
|
||||
~~~cpp
|
||||
//Text can still be added on top, but I already have text on my texture, so I'll leave it blank.
|
||||
button.create(nf::Vec2(0.1, 0.1), "", ap.get("name.button"));
|
||||
~~~
|
||||
|
||||
With these three textures:
|
||||
|
||||
@image html examplebuttonidle.png "Idle" width=20%
|
||||
@image html examplebuttonhover.png "Hover" width=20%
|
||||
@image html examplebuttonpressed.png "Pressed" width=20%
|
||||
|
||||
We get this result:
|
||||
|
||||
@htmlonly
|
||||
|
||||
<video src="buttondemo.mp4" autoplay loop muted width=50%>
|
||||
|
||||
@endhtmlonly
|
||||
|
||||
---
|
||||
|
||||
@section customCubemaps Cubemaps
|
||||
|
||||
Cubemaps are like button textures. Each cubemap consists of 6 textures that are mapped
|
||||
to the inside of a giant, unreachable cube in your scene. The engine takes care of rendering
|
||||
it. All you need to do is supply these 6 textures in your assets with specific filenames.
|
||||
Here, "name" can be anything you choose as an identifier.
|
||||
|
||||
- **name_cmfront** - The front texture (-Z direction)
|
||||
- **name_cmback** - The back texture (+Z direction)
|
||||
- **name_cmright** - The right texture (+X direction)
|
||||
- **name_cmleft** - The left texture (-X direction)
|
||||
- **name_cmtop** - The top texture (+Y direction)
|
||||
- **name_cmbottom** - The bottom texture (-Y direction)
|
||||
|
||||
Once the textures are in place, they can be accessed in your nf::AssetPack like
|
||||
this:
|
||||
|
||||
~~~cpp
|
||||
cubemap.create(ap.get("name.cm"));
|
||||
~~~
|
||||
|
||||
---
|
||||
|
||||
@section customSounds Sounds
|
||||
|
||||
Sounds are the easiest to include.
|
||||
|
||||
All you need to do is place the sound file in your assets and reference it by name
|
||||
when creating an nf::Sound object:
|
||||
|
||||
~~~cpp
|
||||
sound.create(ap.get("sound.ogg"));
|
||||
~~~
|
@ -1,8 +1,9 @@
|
||||
@tableofcontents
|
||||
|
||||
Nothin' Fancy (abbreviated as NF) is an experimental 3D game engine written in C++
|
||||
for Windows. It was created by Grayson Riffe in 2021. This manual aims to aid the end-user
|
||||
with using this engine to create games and visualizations. It contains the
|
||||
for Windows. The engine allows the user to program 3D applications with high-level
|
||||
C++. NF was created by Grayson Riffe in 2021. This manual aims to aid the user
|
||||
with using NF to create games and visualizations. It contains the
|
||||
[user guide](tutorial.html) and the [API reference](namespaces.html).
|
||||
|
||||
@image html logofull.png "Engine Logo" width=15%
|
||||
@ -25,7 +26,7 @@ at any time.
|
||||
- Customizable UI
|
||||
- Text
|
||||
- Textures
|
||||
- Buttons also with customizable textures
|
||||
- Buttons with customizable textures
|
||||
|
||||
Example App
|
||||
===
|
||||
|
@ -3,14 +3,15 @@
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
img:not([src='logofull.png']):not([src="search/mag_sel.svg"]):not([src="doxygen.svg"]):not([src="logo.png"])
|
||||
video, img:not([src="logo.png"]):not([src='logofull.png']):not([src="search/mag_sel.svg"]):not([src="doxygen.svg"])
|
||||
{
|
||||
box-shadow: 0.5em 0.5em 0.5em grey;
|
||||
filter: drop-shadow(0.5em 0.5em 0.5em grey);
|
||||
}
|
||||
|
||||
div.caption
|
||||
{
|
||||
margin-top: 0.5em;
|
||||
margin-top: 0.2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
#nav-sync
|
||||
|