Small improvements; User guide work
| @ -340,14 +340,8 @@ namespace nf { | |||||||
| 
 | 
 | ||||||
| 				m_fpsClock2 = std::chrono::steady_clock::now(); | 				m_fpsClock2 = std::chrono::steady_clock::now(); | ||||||
| 				m_fpsDuration = m_fpsClock2 - m_fpsClock1; | 				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); | 					m_FPS = (int)std::round(1.0 / m_deltaTime); | ||||||
| #ifdef NFDEBUG |  | ||||||
| 					static int i = 0; |  | ||||||
| 					i++; |  | ||||||
| 					if (i % 5 == 0) |  | ||||||
| 						NFLog("FPS: " + std::to_string(m_FPS)); |  | ||||||
| #endif |  | ||||||
| 					m_fpsClock1 = std::chrono::steady_clock::now(); | 					m_fpsClock1 = std::chrono::steady_clock::now(); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -35,9 +35,9 @@ namespace nf { | |||||||
| 			printCurrentTime(); | 			printCurrentTime(); | ||||||
| 		std::printf("NF "); | 		std::printf("NF "); | ||||||
| 		SetConsoleTextAttribute(cmd, 6); | 		SetConsoleTextAttribute(cmd, 6); | ||||||
| 		std::printf("Log: "); | 		std::printf("Log"); | ||||||
| 		SetConsoleTextAttribute(cmd, 7); | 		SetConsoleTextAttribute(cmd, 7); | ||||||
| 		std::printf("%s\n", in); | 		std::printf(": %s\n", in); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Debug::LogImp(const std::string& in) { | 	void Debug::LogImp(const std::string& in) { | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ namespace nf { | |||||||
| 	 * A cubemap is a cube with a texture on each one of its 6 sides. | 	 * A cubemap is a cube with a texture on each one of its 6 sides. | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @sa @ref createCubemapTut | 	 * @sa @ref createCubemapTut | ||||||
| 	 * @ref customCubemap | 	 * @ref customCubemaps | ||||||
| 	*/ | 	*/ | ||||||
| 	class Cubemap : public Drawable, public NFObject { | 	class Cubemap : public Drawable, public NFObject { | ||||||
| 	public: | 	public: | ||||||
|  | |||||||
| 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/custommodel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 547 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: 706 KiB | 
| @ -50,11 +50,11 @@ top toolbar. | |||||||
| Once the solution has been opened, you can find the `main.cpp` file inside the `src` folder | Once the solution has been opened, you can find the `main.cpp` file inside the `src` folder | ||||||
| as shown below. | as shown below. | ||||||
| 
 | 
 | ||||||
| @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 | 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 | @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. | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ from `main`. Most of the code that programs the engine's behavior should be call | |||||||
| your state's [update function](@ref nf::Gamestate::update). | your state's [update function](@ref nf::Gamestate::update). | ||||||
| 
 | 
 | ||||||
| To allow a translate unit to use the engine, you must include `NothinFancy.h`. This | 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 | @section createConfigTut Creating a Config | ||||||
| 
 | 
 | ||||||
| @ -29,9 +29,8 @@ engine should display on the screen. nf::Config has these fields: | |||||||
| 
 | 
 | ||||||
| - `width` - The width of the window if `fullscreen` is set to `false` | - `width` - The width of the window if `fullscreen` is set to `false` | ||||||
| - `height` - The height 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 | - `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: | To create a 1280 by 720 window with a title of "NF Example", you would write: | ||||||
| 
 | 
 | ||||||
| @ -336,12 +335,92 @@ After rendering, our world will have a background. | |||||||
| @section customAssetsTut Adding Your Assets | @section customAssetsTut Adding Your Assets | ||||||
| 
 | 
 | ||||||
| NF's asset system builds your assets into NFPacks that the engine reads at runtime. The | 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 | external tool `NFAssetBuilder.exe` creates these for you. You can then access these packs | ||||||
| see @ref assets. | 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 | @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 debuggingTut Debugging Your App | @section debuggingTut Debugging Your App | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,14 +1,100 @@ | |||||||
| @page assets Asset System | @page assets Asset System | ||||||
| @tableofcontents | @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 | @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 customModels Models | ||||||
| 
 | 
 | ||||||
| @section customCubemap Custom Cubemap Assets | 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 | ||||||
|  | 
 | ||||||
|  | @section customButtons Button Textures | ||||||
|  | 
 | ||||||
|  | @section customCubemaps Cubemaps | ||||||
|  | 
 | ||||||
|  | @section customSounds Sounds | ||||||
| @ -5,7 +5,7 @@ | |||||||
| 
 | 
 | ||||||
| img:not([src='logofull.png']):not([src="search/mag_sel.svg"]):not([src="doxygen.svg"]):not([src="logo.png"]) | img:not([src='logofull.png']):not([src="search/mag_sel.svg"]):not([src="doxygen.svg"]):not([src="logo.png"]) | ||||||
| { | { | ||||||
| 		box-shadow: 0.5em 0.5em 0.5em grey; | 		filter: drop-shadow(0.5em 0.5em 0.5em grey); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| div.caption | div.caption | ||||||
|  | |||||||
 Grayson Riffe (Laptop)
						Grayson Riffe (Laptop)