{"id":383,"date":"2021-11-30T21:09:35","date_gmt":"2021-11-30T21:09:35","guid":{"rendered":"https:\/\/writingagame.com\/?p=383"},"modified":"2021-12-04T18:57:03","modified_gmt":"2021-12-04T18:57:03","slug":"chapter-7-external-data-files-windows","status":"publish","type":"post","link":"https:\/\/writingagame.com\/index.php\/2021\/11\/30\/chapter-7-external-data-files-windows\/","title":{"rendered":"Chapter 7. External data files, Windows"},"content":{"rendered":"\n<p>Now we are ready to start writing real (practically usable) shaders. Right now we have 2 sample (1 vertex and 1 fragment) shaders, that are hard-coded in TheGame.cpp. Obviously, not the best solution, but for simplicity&#8217;s sake was quite reasonable. In our turn, we want to keep our shaders outside of the executable.<\/p>\n\n\n\n<p>1. In <strong>Windows File Explorer<\/strong> (not in VS), in <em>C:\\CPP\\engine\\<\/em> folder add sub-folder \u201cdt\u201d (for &#8220;data&#8221;). Here we will keep all engine-related data files, particularly shaders. Inside of \u201cdt\u201d add sub-folder \u201cshaders\u201d.<\/p>\n\n\n\n<p>In a <strong>Text Editor<\/strong> create a simple txt file for testing, just couple lines, such as<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ntest 1\ntest 2\n<\/pre><\/div>\n\n\n<p><br>Save it as <em>C:\\CPP\\engine\\dt\\shaders\\test0.txt<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p>2. Now we need to pass this file to the executable. There are couple options such as including files into &#8220;resources&#8221; or directly into the project. However, we don&#8217;t want data files &#8220;inside&#8221; of the project. Instead, we will instruct Visual Studio to copy data folder to the same folder as executable.<\/p>\n\n\n\n<p>Start Visual Studio, open <em>C:\\CPP\\a999hello\\p_windows\\p_windows.sln<\/em> solution.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p>3. Open  <em>p_windows<\/em> project Properties, All Configurations \/ Win32, <em>Configuration Properties -&gt; Build events -&gt; Post-Build Event<\/em>, open <em>Command Line -&gt; Edit<\/em>.<\/p>\n\n\n\n<p>Add (copy-paste) following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xcopy \"..\\..\\engine\\dt\\*.*\" \"$(TargetDir)dt\\\" \/E \/R \/D \/y<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>Then &#8211; <strong>Ok, Apply, Ok<\/strong>.<\/p>\n\n\n\n<p>Clarification:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>xcopy <\/strong>&#8211; doesn&#8217;t really need an explanation (I guess)<\/li><li><strong>&#8220;..\\..\\engine\\dt\\*.*&#8221;<\/strong> \u2013 copy what and from. Refers to <em>C:\\CPP\\engine\\dt<\/em>, just in relative form from  <em>p_windows<\/em>  project root folder<\/li><li><strong>&#8220;$(TargetDir)dt\\&#8221;<\/strong> &#8211; copy to where. We want a copy of \u201cdt\u201d folder in the same place as executable<\/li><\/ul>\n\n\n\n<p>Keys:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>\/E<\/strong> &#8211; Copy directories and subdirectories, including empty ones<\/li><li><strong>\/R<\/strong> &#8211; Overwrite read-only files<\/li><li><strong>\/D<\/strong> \u2013 Copy files only if newer<\/li><li><strong>\/y<\/strong> &#8211; Don&#8217;t ask if exists\/overwrite<\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p>4. Now run the program (green arrow). Runs. Now &#8211; close the program OR: <em>VS top menu -&gt; Debug -&gt; Stop Debugging<\/em>.<\/p>\n\n\n\n<p>Go to <strong>Windows File Explorer<\/strong>, open <em>C:\\CPP\\a999hello\\p_windows\\Debug<\/em>. Perfect, the copy of the &#8220;dt&#8221; folder with all it&#8217;s content is there, in the same folder as <em>OurProject.exe<\/em>:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c07\/01.jpg\"><\/p>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>5. Now let&#8217;s try to read our test file (test0.txt). For that we need to specify the file&#8217;s <strong>full<\/strong> path. However, it can vary depending on where program was installed. So, will need to find it out, to detect application&#8217;s root folder.<\/p>\n\n\n\n<p>The code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    \/\/find application root folder\n    char path&#91;256];\n    GetModuleFileNameA(NULL, path, 256);\n    filesRoot.assign(path);\n    int lastSlashPos = filesRoot.find_last_of(&#039;\\\\&#039;);\n    if (lastSlashPos &lt; 0)\n        lastSlashPos = filesRoot.find_last_of(&#039;\/&#039;);\n    filesRoot = filesRoot.substr(0, lastSlashPos);\n    mylog(&quot;App path = %s\\n&quot;, filesRoot.c_str());\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Insert it in <em>main.cpp<\/em> right before <em>theGame.run()<\/em>.<\/p>\n\n\n\n<p>Also, add after include section:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include &lt;windows.h&gt;\n#include &lt;string&gt;\n#include &lt;fstream&gt;      \/\/ std::ifstream\n\nstd::string filesRoot;\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Run. Result:<\/p>\n\n\n\n<p><strong>App path = C:\\CPP\\a999hello\\p_windows\\Debug<\/strong><\/p>\n\n\n\n<p>Just what we need. <\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>6. Now let&#8217;s open our test file and read it.<\/p>\n\n\n\n<p>After <em>mylog(\u2026)<\/em> add following code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    \/\/reading test file\n    std::ifstream myFile(filesRoot + &quot;\/dt\/shaders\/test0.txt&quot;);\n    std::string line;\n    if (myFile.is_open())\n    {\n        while (getline(myFile, line))\n            mylog(&quot;%s\\n&quot;, line.c_str());\n    }\n    else mylog(&quot;Unable to open file\\n&quot;);\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Run. Result:<\/p>\n\n\n\n<p><strong>App path = C:\\CPP\\a999hello\\p_windows\\Debug<\/strong><br><strong>test 1<br>test 2<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>7. After removing testing code, <em>main.cpp<\/em> (with new <em>filesRoot <\/em>variable and with corresponding code) is:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; highlight: [10,11,12,13,52,53,54,55,56,57,58,59,60]; title: ; notranslate\" title=\"\">\n#include &lt;glad\/glad.h&gt;\n#define GLFW_INCLUDE_NONE\n#include &lt;GLFW\/glfw3.h&gt;\n\n#include &lt;stdlib.h&gt;\n\n#include &quot;TheGame.h&quot;\n#include &quot;platform.h&quot;\n\n#include &lt;windows.h&gt;\n#include &lt;string&gt;\n\nstd::string filesRoot;\n\nstatic void error_callback(int error, const char* description)\n{\n    mylog(&quot;Error: %s\\n&quot;, description);\n}\n\nstatic void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)\n{\n    if (key == GLFW_KEY_ESCAPE &amp;&amp; action == GLFW_PRESS)\n        glfwSetWindowShouldClose(window, GLFW_TRUE);\n}\n\nTheGame theGame;\nGLFWwindow* myMainWindow;\n\nint main(void)\n{\n    glfwSetErrorCallback(error_callback);\n\n    if (!glfwInit())\n        exit(EXIT_FAILURE);\n\n    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);\n    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);\n\n    myMainWindow = glfwCreateWindow(640, 480, &quot;OurProject&quot;, NULL, NULL);\n    if (!myMainWindow)\n    {\n        glfwTerminate();\n        exit(EXIT_FAILURE);\n    }\n\n    glfwSetKeyCallback(myMainWindow, key_callback);\n\n    glfwMakeContextCurrent(myMainWindow);\n    gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress); \/\/gladLoadGL(glfwGetProcAddress);\n    glfwSwapInterval(1);\n\n    \/\/find application root folder\n    char path&#91;256];\n    GetModuleFileNameA(NULL, path, 256);\n    filesRoot.assign(path);\n    int lastSlashPos = filesRoot.find_last_of(&#039;\\\\&#039;);\n    if (lastSlashPos &lt; 0)\n        lastSlashPos = filesRoot.find_last_of(&#039;\/&#039;);\n    filesRoot = filesRoot.substr(0, lastSlashPos);\n    mylog(&quot;App path = %s\\n&quot;, filesRoot.c_str());\n    \n    theGame.run();\n\n    glfwDestroyWindow(myMainWindow);\n    glfwTerminate();\n    exit(EXIT_SUCCESS);\n}\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Replace  <em>main.cpp<\/em> code by this one.<\/p>\n\n\n\n<p>Save All.<\/p>\n\n\n\n<p>What&#8217;s next? Finally, shaders?? No. First &#8211; external data files on Android.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p class=\"mb-2\">Now we are ready to start writing real (practically usable) shaders. Right now we have 2 sample (1 vertex and 1 fragment) shaders, that are hard-coded in TheGame.cpp. Obviously, not the best solution, but for simplicity&#8217;s sake was quite reasonable. In our turn, we want to keep our shaders outside of the executable. 1. In [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-383","post","type-post","status-publish","format-standard","hentry","category-cross-platform-3d"],"_links":{"self":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/383","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/comments?post=383"}],"version-history":[{"count":10,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/383\/revisions"}],"predecessor-version":[{"id":472,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/383\/revisions\/472"}],"wp:attachment":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media?parent=383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/categories?post=383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/tags?post=383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}