antispam-bee domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/ruwritingagame/public_html/wp-includes/functions.php on line 6131\u0422\u0435\u043f\u0435\u0440\u044c \u044f \u0445\u043e\u0447\u0443 “\u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c” \u0441\u0442\u044b\u043a (\u0449\u0435\u043b\u044c) \u043c\u0435\u0436\u0434\u0443 \u043f\u0430\u0447\u043a\u043e\u0439 \u0438 \u043a\u0440\u044b\u0448\u043a\u043e\u0439, \u043a\u0430\u043a normal map<\/em> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u043a \u0447\u0430\u0441\u0442\u0438<\/strong> \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438, \u041d\u0415 \u043a\u043e \u0432\u0441\u0435\u0439 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438, \u0438 \u041d\u0415 \u043a VirtualShape <\/em>\u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u0440\u0430\u043d\u044c\u0448\u0435. \u042d\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439.<\/p>\n\n\n\n 1. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c VS, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c C:\\CPP\\a997modeler\\p_windows\\p_windows.sln<\/em>.<\/p>\n\n\n\n \u041f\u0435\u0440\u0432\u0430\u044f \u0438\u0437 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439 – \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u043e\u0432\/\u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432<\/strong>, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0438\u0437 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e \u0438\u043c\u0435\u043d\u0438 (\u043c\u0435\u0442\u043a\u0435).<\/p>\n\n\n\n 2. \u0417\u0430\u043c\u0435\u043d\u0438\u043c Group01.h<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n <\/p>\n\n\n\n 3. \u0417\u0430\u043c\u0435\u043d\u0438\u043c Vertex01.h<\/em> \u043a\u043e\u0434 \u043d\u0430: <\/p>\n\n\n <\/p>\n\n\n\n 4. \u0417\u0430\u043c\u0435\u043d\u0438\u043c Triangle01.h<\/em> \u043a\u043e\u0434 \u043d\u0430: <\/p>\n\n\n <\/p>\n\n\n\n \u041a\u043b\u0430\u0441\u0441 GroupTransform<\/strong> \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0447\u0442\u043e <\/strong>\u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438, \u043d\u0443 \u0438 \u0447\u0442\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u044d\u0442\u043e\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u043e\u0439.<\/p>\n\n\n\n 5. \u0417\u0430\u043c\u0435\u043d\u0438\u043c GroupTransform.h<\/em> \u043a\u043e\u0434 \u043d\u0430: <\/p>\n\n\n <\/p>\n\n\n\n 6. \u0417\u0430\u043c\u0435\u043d\u0438\u043c GroupTransform.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430: <\/p>\n\n\n <\/p>\n\n\n\n \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 root01.txt<\/strong> \u043f\u0430\u0440\u0443 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n\n\n\n 7. \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043d\u0438\u0436\u0435\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432 \u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440<\/strong> \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0435\u0433\u043e (overwrite) to\/as<\/p>\n\n\n\n C:\\CPP\\a997modeler\\dt\\models\\misc\\marlboro01\\root01.txt<\/em><\/p>\n\n\n <\/p>\n\n\n\n \u0414\u043b\u044f \u043f\u0440\u0438\u0435\u043c\u0430 \u043d\u043e\u0432\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u043a\u043b\u0430\u0441\u0441\u044b XMLParser,<\/strong> ModelBuilder1base <\/strong>\u0438 ModelLoader <\/strong>\u0441\u043b\u0435\u0433\u043a\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b.<\/p>\n\n\n\n 8. \u0417\u0430\u043c\u0435\u043d\u0438\u043c XMLParser.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n <\/p>\n\n\n\n \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n\n\n\n 9. \u0417\u0430\u043c\u0435\u043d\u0438\u043c ModelBuilder1base.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n <\/p>\n\n\n\n \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n\n\n\n 10. \u0417\u0430\u043c\u0435\u043d\u0438\u043c ModelLoader.h<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n <\/p>\n\n\n\n \u041d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n\n\n\n 11. \u0417\u0430\u043c\u0435\u043d\u0438\u043c ModelLoader.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n <\/p>\n\n\n\n \u0422\u0430\u043a\u0436\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b:<\/p>\n\n\n\n \u0418\u0442\u0430\u043a, \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u043b\u0438\u0441\u044c \u043f\u043e\u043c\u0435\u0442\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443, \u0438 \u043f\u043e\u0442\u043e\u043c \u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044c \u0435\u0435 \u0432\u043f\u0440\u0430\u0432\u043e \u043d\u0430 5 units.<\/p>\n\n\n\n 12. \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n\n\n\n <\/p>\n\n\n\n \u0421\u0434\u0432\u0438\u043d\u0443\u043b\u0438. \u041e\u0434\u043d\u0430\u043a\u043e, \u0437\u043e\u043b\u043e\u0447\u0435\u043d\u044b\u0435 \u0431\u0443\u043a\u0432\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043f\u043e\u0437\u0430\u0434\u0438<\/strong>, \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0441\u0434\u0432\u0438\u043d\u0443\u0442\u0443\u044e \u043f\u0440\u0430\u0432\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443. \u0422\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043d\u0435 \u043e\u0437\u0430\u0431\u043e\u0442\u0438\u043b\u0438\u0441\u044c depth buffer<\/strong>-\u043e\u043c (z-buffer). \u0411\u043e\u043b\u0435\u0435 \u0431\u043b\u0438\u0437\u043a\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0438\u0435. \u0410 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0434\u043e “\u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0431\u0443\u0444\u0435\u0440\u0430 \u0433\u043b\u0443\u0431\u0438\u043d\u044b” (enable depth buffer testing<\/em>).<\/p>\n\n\n\n 13. \u0417\u0430\u043c\u0435\u043d\u0438\u043c TheGame.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n <\/p>\n\n\n\n \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438. \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e:<\/p>\n\n\n\n 14. \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n\n\n\n <\/p>\n\n\n\n \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, depth buffer \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n\n\n\n \u0418\u0442\u0430\u043a, \u043c\u044b \u043c\u043e\u0436\u0435\u043c<\/strong> \u043f\u043e\u043c\u0435\u0442\u0438\u0442\u044c sub-mesh \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e, \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u0430.<\/p>\n\n\n\n \u0422\u0435\u043f\u0435\u0440\u044c<\/p>\n\n\n\n \u041a \u043c\u043e\u0435\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u044e depth buffer<\/em> \u043d\u0430 \u0410\u043d\u0434\u0440\u043e\u0438\u0434\u0435 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b! \u041e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0415 \u0431\u044b\u043b \u0432\u043a\u043b\u044e\u0447\u0435\u043d \u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e GL-\u0430 \u0432 main.cpp<\/em>.<\/p>\n\n\n\n 15. \u041f\u0435\u0440\u0435-\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c VS. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c\u00a0C:\\CPP\\a997modeler\\p_android\\p_android.sln<\/em>.<\/p>\n\n\n\n 16. \u0417\u0430\u043c\u0435\u043d\u0438\u043c main.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n <\/p>\n\n\n\n \u0412\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c 1 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430… (\u0441\u0442\u0440\u043e\u043a\u0430 39).<\/p>\n\n\n\n 17. \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c, \u0440\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c, \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u043c.<\/p>\n\n\n\n \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a. \u0422\u0435\u043f\u0435\u0440\u044c – \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n\n\n\n VS top menu -> Debug -> Stop Debugging<\/em><\/p>\n\n\n\n <\/p>\n","protected":false},"excerpt":{"rendered":" \u0422\u0435\u043f\u0435\u0440\u044c \u044f \u0445\u043e\u0447\u0443 “\u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c” \u0441\u0442\u044b\u043a (\u0449\u0435\u043b\u044c) \u043c\u0435\u0436\u0434\u0443 \u043f\u0430\u0447\u043a\u043e\u0439 \u0438 \u043a\u0440\u044b\u0448\u043a\u043e\u0439, \u043a\u0430\u043a normal map \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u043a \u0447\u0430\u0441\u0442\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438, \u041d\u0415 \u043a\u043e \u0432\u0441\u0435\u0439 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438, \u0438 \u041d\u0415 \u043a VirtualShape \u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u0440\u0430\u043d\u044c\u0448\u0435. \u042d\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439. Windows 1. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c VS, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c C:\\CPP\\a997modeler\\p_windows\\p_windows.sln. \u041f\u0435\u0440\u0432\u0430\u044f \u0438\u0437 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439 – \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0432\u0435\u0440\u0442\u0435\u043a\u0441\u043e\u0432\/\u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u043a\u0430\u043a\u043e\u0439-\u0442\u043e […]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-1003","post","type-post","status-publish","format-standard","hentry","category-cross-platform-3d"],"_links":{"self":[{"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/posts\/1003","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/comments?post=1003"}],"version-history":[{"count":11,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/posts\/1003\/revisions"}],"predecessor-version":[{"id":1494,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/posts\/1003\/revisions\/1494"}],"wp:attachment":[{"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/media?parent=1003"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/categories?post=1003"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/tags?post=1003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}Windows<\/h2>\n\n\n\n
\n\n\n\n\n#pragma once\n\nclass Group01\n{\npublic:\n\tchar marks[124] = "";\n\tint fromVertexN = 0;\n\tint fromTriangleN = 0;\n};\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#pragma once\n\nclass Vertex01\n{\npublic:\n\tchar marks[124] = "";\n\tint subjN = -1; \/\/game subject number\n\tint materialN = -1; \/\/material number\n\tint flag = 0;\n\tint endOfSequence = 0; \/\/for sequentional (unindexed) primitives (like GL_LINE_STRIP for example)\n\tint altN = -1; \/\/vertex' position in alternative array\n\t\/\/atributes\n\tfloat aPos[4] = { 0,0,0,0 }; \/\/position x,y,z + 4-th float for matrix operations\n\tfloat aNormal[4] = { 0,0,0,0 }; \/\/normal (surface reflection vector) x,y,z + 4-th float for matrix operations\n\tfloat aTuv[2] = { 0,0 }; \/\/2D texture coordinates\n\tfloat aTuv2[2] = { 0,0 }; \/\/for normal maps\n\t\/\/tangent space (for normal maps)\n\tfloat aTangent[3] = { 0,0,0 };\n\tfloat aBinormal[3] = { 0,0,0 };\n};\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#pragma once\n\nclass Triangle01\n{\npublic:\n\tchar marks[124] = "";\n\tint subjN = -1; \/\/game subject number\n\tint materialN = -1; \/\/material number\n\tint flag = 0;\n\tint idx[3] = { 0,0,0 }; \/\/3 vertex indices\n};\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#pragma once\n#include <stdlib.h>\n#include "ModelBuilder1base.h"\n\nclass GroupTransform\n{\npublic:\n\tfloat shift[4] = { 0,0,0,0 };\n\tfloat spin[3] = { 0,0,0 }; \/\/in degrees\n\tfloat scale[3] = { 1,1,1 };\n\tstd::string allign = "";\n\tstd::string headZto = "";\n\tstd::string onThe = ""; \/\/left\/right\/etc.\n\t\/\/limit to\n\tGroup01* pGroup = NULL; \/\/NULL-all, can also be pCurrentGroup or pLastClosedGroup\n\tchar mark[32] = ""; \/\/must be in <>\n\tfloat pMin[3]{ -1000000 ,-1000000 ,-1000000 };\n\tfloat pMax[3]{ 1000000 , 1000000 , 1000000 };\npublic:\n\tint executeGroupTransform(ModelBuilder1base* pMB) { return executeGroupTransform(pMB, this); };\n\tstatic int executeGroupTransform(ModelBuilder1base* pMB, GroupTransform* pGT);\n\t\/\/set limits\n\tstatic void limit2mark(GroupTransform* pGT, std::string mark0);\n\tstatic int flagSelection(GroupTransform* pGT, std::vector<Vertex01*>* pVertices, std::vector<Triangle01*>* pTriangles);\n\tstatic int cloneFlagged(ModelBuilder1base* pMB,\n\t\tstd::vector<Vertex01*>* pVxDst, std::vector<Triangle01*>* pTrDst,\n\t\tstd::vector<Vertex01*>* pVxSrc, std::vector<Triangle01*>* pTrSrc);\n\tstatic int refactorTriangles(std::vector<Triangle01*>* pTrDst, int trianglesN0dst, std::vector<Vertex01*>* pVxSrc);\n\tstatic int transformFlagged(GroupTransform* pGT, std::vector<Vertex01*>* pVxDst);\n\tstatic int transformFlaggedMx(std::vector<Vertex01*>* pVx, mat4x4* pTransformMatrix);\n\n\tstatic int buildTransformMatrix(GroupTransform* pGT, mat4x4* pTransformMatrix);\n\tstatic void flagAll(std::vector<Vertex01*>* pVx, std::vector<Triangle01*>* pTr);\n\tstatic int buildBoundingBoxFlagged(float* bbMin, float* bbMax, std::vector<Vertex01*>* pVx);\n};\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#include "GroupTransform.h"\n#include "utils.h"\n\nextern float degrees2radians;\n\nint GroupTransform::executeGroupTransform(ModelBuilder1base* pMB, GroupTransform* pGT) {\n\t\/\/pMB->moveGroupDg(pMB, pGT->spin[0], pGT->spin[1], pGT->spin[2], pGT->shift[0], pGT->shift[1], pGT->shift[2]);\n\tflagSelection(pGT, &pMB->vertices, &pMB->triangles);\n\ttransformFlagged(pGT, &pMB->vertices);\n\treturn 1;\n}\nvoid GroupTransform::limit2mark(GroupTransform* pGT, std::string mark0) {\n\tstd::string outStr;\n\toutStr.append("<" + mark0 + ">");\n\tmyStrcpy_s(pGT->mark, 32, outStr.c_str());\n}\nint GroupTransform::flagSelection(GroupTransform* pGT, std::vector<Vertex01*>* pVertices, std::vector<Triangle01*>* pTriangles) {\n\tif (pVertices != NULL) {\n\t\tbool checkSize = false;\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tif (pGT->pMin[i] > -1000000) {\n\t\t\t\tcheckSize = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pGT->pMax[i] < 1000000) {\n\t\t\t\tcheckSize = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tint totalN = pVertices->size();\n\t\tfor (int vN = 0; vN < totalN; vN++) {\n\t\t\tVertex01* pV = pVertices->at(vN);\n\t\t\tif (pGT->pGroup != NULL) {\n\t\t\t\tif (vN < pGT->pGroup->fromVertexN) {\n\t\t\t\t\tpV->flag = -1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (strcmp(pGT->mark, "") != 0) {\n\t\t\t\tif (strstr(pV->marks, pGT->mark) == nullptr) {\n\t\t\t\t\tpV->flag = -1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (checkSize) {\n\t\t\t\tbool fits = true;\n\t\t\t\tfor (int i = 0; i < 3; i++) {\n\t\t\t\t\tif (pV->aPos[i] < pGT->pMin[i]) {\n\t\t\t\t\t\tfits = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (pV->aPos[i] > pGT->pMax[i]) {\n\t\t\t\t\t\tfits = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!fits) {\n\t\t\t\t\tpV->flag = -1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpV->flag = 0;\n\t\t}\n\t}\n\tif (pTriangles != NULL) {\n\t\tint totalN = pTriangles->size();\n\t\tfor (int tN = 0; tN < totalN; tN++) {\n\t\t\tTriangle01* pT = pTriangles->at(tN);\n\t\t\tif (pGT->pGroup != NULL) {\n\t\t\t\tif (tN < pGT->pGroup->fromTriangleN) {\n\t\t\t\t\tpT->flag = -1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (strcmp(pGT->mark, "") != 0) {\n\t\t\t\tif (strstr(pT->marks, pGT->mark) == nullptr) {\n\t\t\t\t\tpT->flag = -1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpT->flag = 0;\n\t\t}\n\t}\n\treturn 1;\n}\nint GroupTransform::cloneFlagged(ModelBuilder1base* pMB,\n\tstd::vector<Vertex01*>* pVxDst, std::vector<Triangle01*>* pTrDst,\n\tstd::vector<Vertex01*>* pVxSrc, std::vector<Triangle01*>* pTrSrc) {\n\tint vertsNsrc = pVxSrc->size();\n\tint trianglesNsrc = pTrSrc->size();\n\tint vertsN0dst = pVxDst->size();\n\tint trianglesN0dst = pTrDst->size();\n\tfor (int i = 0; i < vertsNsrc; i++) {\n\t\tVertex01* pV0 = pVxSrc->at(i);\n\t\tif (pV0->flag < 0)\n\t\t\tcontinue;\n\t\tpV0->altN = pVxDst->size();\n\t\tVertex01* pV = new Vertex01(*pV0);\n\t\tpVxDst->push_back(pV);\n\t\t\/\/overwrite marks\n\t\tif (pMB != NULL) {\n\t\t\tmyStrcpy_s(pV->marks, 124, pMB->pCurrentGroup->marks);\n\t\t\tpV->subjN = pMB->usingSubjN;\n\t\t}\n\t\tpV->flag = -1;\n\t}\n\tfor (int i = 0; i < trianglesNsrc; i++) {\n\t\tTriangle01* pT0 = pTrSrc->at(i);\n\t\tif (pT0->flag < 0)\n\t\t\tcontinue;\n\t\tTriangle01* pT = new Triangle01(*pT0);\n\t\tpTrDst->push_back(pT);\n\t\t\/\/overwrite marks\n\t\tif (pMB != NULL) {\n\t\t\tmyStrcpy_s(pT->marks, 124, pMB->pCurrentGroup->marks);\n\t\t\tpT->subjN = pMB->usingSubjN;\n\t\t}\n\t\tpT->flag = -1;\n\t}\n\trefactorTriangles(pTrDst, trianglesN0dst, pVxSrc);\n\treturn 1;\n}\nint GroupTransform::refactorTriangles(std::vector<Triangle01*>* pTrDst, int trianglesN0dst, std::vector<Vertex01*>* pVxSrc){\n\t\/\/re-factor triangles idx, adjusting triangles verts #s\n\tint trianglesNdst = pTrDst->size();\n\tfor (int tN = trianglesN0dst; tN < trianglesNdst; tN++) {\n\t\tTriangle01* pT = pTrDst->at(tN);\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tint vN = pT->idx[i];\n\t\t\tVertex01* pV = pVxSrc->at(vN);\n\t\t\tpT->idx[i] = pV->altN;\n\t\t}\n\t}\n\treturn 1;\n}\nint GroupTransform::buildTransformMatrix(GroupTransform* pGT, mat4x4* pTransformMatrix) {\n\tmat4x4_identity(*pTransformMatrix);\n\tif (!pGT->onThe.empty()) {\n\t\tif (pGT->onThe.compare("back") == 0)\n\t\t\tmat4x4_rotate_Y(*pTransformMatrix, *pTransformMatrix, degrees2radians * 180);\n\t\telse if (pGT->onThe.compare("left") == 0)\n\t\t\tmat4x4_rotate_Y(*pTransformMatrix, *pTransformMatrix, -degrees2radians * 90);\n\t\telse if (pGT->onThe.compare("right") == 0)\n\t\t\tmat4x4_rotate_Y(*pTransformMatrix, *pTransformMatrix, degrees2radians * 90);\n\t\telse if (pGT->onThe.compare("top") == 0) {\n\t\t\tmat4x4_rotate_Y(*pTransformMatrix, *pTransformMatrix, degrees2radians * 180);\n\t\t\tmat4x4_rotate_X(*pTransformMatrix, *pTransformMatrix, -degrees2radians * 90);\n\t\t}\n\t\telse if (pGT->onThe.compare("bottom") == 0)\n\t\t\tmat4x4_rotate_X(*pTransformMatrix, *pTransformMatrix, degrees2radians * 90);\n\t}\n\tif(!v3equals(pGT->shift, 0))\n\t\tmat4x4_translate_in_place(*pTransformMatrix, pGT->shift[0], pGT->shift[1], pGT->shift[2]);\n\n\t\/\/rotation order: Z-X-Y\n\tif (pGT->spin[1] != 0)\n\t\tmat4x4_rotate_Y(*pTransformMatrix, *pTransformMatrix, degrees2radians * pGT->spin[1]);\n\tif (pGT->spin[0] != 0)\n\t\tmat4x4_rotate_X(*pTransformMatrix, *pTransformMatrix, degrees2radians * pGT->spin[0]);\n\tif (pGT->spin[2] != 0)\n\t\tmat4x4_rotate_Z(*pTransformMatrix, *pTransformMatrix, degrees2radians * pGT->spin[2]);\n\n\tif (!v3equals(pGT->scale, 1))\n\t\tmat4x4_scale_aniso(*pTransformMatrix, *pTransformMatrix, pGT->scale[0], pGT->scale[1], pGT->scale[2]);\n\treturn 1;\n}\nint GroupTransform::transformFlagged(GroupTransform* pGT, std::vector<Vertex01*>* pVx) {\n\t\/\/moves and rotates vertex group\n\t\/\/rotation angles are set in degrees\n\tmat4x4 transformMatrix;\n\tbuildTransformMatrix(pGT, &transformMatrix);\n\ttransformFlaggedMx(pVx, &transformMatrix);\n\treturn 1;\n}\nint GroupTransform::transformFlaggedMx(std::vector<Vertex01*>* pVx, mat4x4* pTransformMatrix) {\n\t\/\/moves and rotates vertex group\n\tint vertsN = pVx->size();\n\tfor (int i = 0; i < vertsN; i++) {\n\t\tVertex01* pV = pVx->at(i);\n\t\tif (pV->flag < 0)\n\t\t\tcontinue;\n\t\tmat4x4_mul_vec4plus(pV->aPos, *pTransformMatrix, pV->aPos, 1);\n\t\t\/\/normal\n\t\tmat4x4_mul_vec4plus(pV->aNormal, *pTransformMatrix, pV->aNormal, 0);\n\t\tvec3_norm(pV->aNormal, pV->aNormal);\n\t}\n\treturn 1;\n}\nvoid GroupTransform::flagAll(std::vector<Vertex01*>* pVx, std::vector<Triangle01*>* pTr) {\n\t\/\/set flags\n\tfor (int i = pVx->size() - 1; i >= 0; i--)\n\t\tpVx->at(i)->flag = 0;\n\tfor (int i = pTr->size() - 1; i >= 0; i--)\n\t\tpTr->at(i)->flag = 0;\n}\nint GroupTransform::buildBoundingBoxFlagged(float* bbMin, float* bbMax, std::vector<Vertex01*>* pVx) {\n\tv3copy(bbMin, pVx->at(0)->aPos);\n\tv3copy(bbMax, pVx->at(0)->aPos);\n\t\/\/scan all flagged except #0\n\tfor (int vN = pVx->size() - 1; vN > 0; vN--) {\n\t\tVertex01* pV = pVx->at(vN);\n\t\tif (pV->flag < 0)\n\t\t\tcontinue;\n\t\tfor(int i=0;i<3;i++){\n\t\t\tif (bbMin[i] > pV->aPos[i])\n\t\t\t\tbbMin[i] = pV->aPos[i];\n\t\t\tif (bbMax[i] < pV->aPos[i])\n\t\t\t\tbbMax[i] = pV->aPos[i];\n\t\t}\n\t}\n\treturn 1;\n}\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n<texture_as="tx0" src="marlboro03small.png" ckey="#00ff00"\/>\n<mt_type="phong" uTex0_use="tx0" \/>\n<vs="box_tank" whl="53,83,21" ext=1 sectR=1 \/>\n<a="front v" xywh="2,1,323,495"\/>\n<a="back v" xywh="2,1,323,495"\/>\n<a="right all" xywh="327,1,128,495" mark="box_right"\/>\n<a="left all" xywh="457,1,128,495"\/>\n<a="top" xywh="588,1,323,133"\/>\n<a="bottom" xywh="587,136,324,134"\/>\n\/\/golden prints\n<vs="box" whl="55.1,85.1,23.1" \/>\n<texture_as="whitenoise" src="\/dt\/common\/img\/whitenoise\/wn64_blur3.bmp"\/>\n<texture_as="gold" src="\/dt\/common\/img\/materials\/gold02roman.bmp" \/>\n<mt_type="mirror" uAlphaBlending uTex1mask_use="tx0" uTex1alphaChannelN=1 uTex0_use="whitenoise" uTex0translateChannelN=0 uTex3_use="gold" \/>\n\/\/side golden prints\n<a="right" xywh="342,12,101,10" whl="x,1.8,18.1" pxyz="x,39.8, -0.3" \/> \/\/Please do not litter\n<a="right" xywh="339,144,105,89" whl="x,15.35,18.9" pxyz="x,10.3,-0.12" \/> \/\/For special offers...\n<a="left" xywh="475,15,95,48" whl="x,8.4,17" pxyz="x,36, 0.3" \/> \/\/Underage sale...\n\/\/front prints\n<group>\n\t\/\/bottom golden print "20 class a..."\n\t<a="front" xywh="20,498,289,13" whl="47.5,2,x" pxyz="1,-36,x" \/>\n\t\/\/blazon\/emblem\n\t<mt_type="mirror" uAlphaBlending uTex2nm_use="tx0" uTex0_use="whitenoise" uTex0translateChannelN=0 uTex3_use="gold" \/>\n\t<a="front" xywh2nm="589,415,128,94" whl="20.7,16,x" pxyz="0.3,6.1,x" \/> \/\/emblem\n\t\/\/"Marlboro\n\t<mt_type="phong" uAlphaBlending uTex2nm_use="tx0" uColor="#1E211E" \/>\n\t<a="front" xywh2nm="590,275,301,136" whl="49.2,23.3,x" pxyz="0.21,-18,x" \/> \/\/marlboro\n<\/group> \n<clone ay=180 \/>\n\n<do px=5 all markedAs="box_right" \/>\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#include "XMLparser.h"\n#include "platform.h"\n#include "utils.h"\n#include "MyColor.h"\n#include <vector>\n\nextern std::string filesRoot;\n\nint XMLparser::removeComments(XMLparser* pXP) {\n\t\/\/find all occurances of "\/*"\n\tstd::vector<char*> commentsStarts;\n\t\/\/ \/* comments *\/\n\tchar* scanFrom = pXP->pData;\n\twhile (1) {\n\t\tchar* commentStarts = strstr(scanFrom, "\/*");\n\t\tif (commentStarts == NULL)\n\t\t\tbreak;\n\t\tcommentsStarts.push_back(commentStarts);\n\t\tscanFrom = commentStarts + 2;\n\t}\n\t\/\/here we have a list of \/* comments *\/\n\twhile(commentsStarts.size() > 0){\n\t\t\/\/get last comment\n\t\tchar* commentStarts = commentsStarts.back();\n\t\tcommentsStarts.pop_back();\n\t\tchar* commentEnds = strstr(commentStarts, "*\/");\n\t\tint commentLength = (int)(commentEnds - commentStarts) + 2;\n\t\t\/\/shift text left\n\t\tmyStrcpy_s(commentStarts, pXP->dataSize - (int)(commentStarts - pXP->pData), commentStarts + commentLength);\n\t\tpXP->dataSize -= commentLength;\n\/\/mylog("======\\n%s----------\\n", pXP->pData);\n\t}\n\t\/\/ \/\/line comments\n\tscanFrom = pXP->pData;\n\twhile (1) {\n\t\tchar* commentStarts = strstr(scanFrom, "\/\/");\n\t\tif (commentStarts == NULL)\n\t\t\tbreak;\n\t\tchar* commentEnds = strstr(commentStarts, "\\n");\n\t\tint commentLength = (int)(commentEnds - commentStarts) + 1;\n\t\t\/\/shift text left\n\t\tmyStrcpy_s(commentStarts, pXP->dataSize - (int)(commentStarts - pXP->pData), commentStarts + commentLength);\n\t\tpXP->dataSize -= commentLength;\n\t\tscanFrom = commentStarts;\n\/\/mylog("======\\n%s----------\\n", pXP->pData);\n\t}\n\t\/\/ <!-- comments -->\n\tscanFrom = pXP->pData;\n\twhile (1) {\n\t\tchar* commentStarts = strstr(scanFrom, "<!--");\n\t\tif (commentStarts == NULL)\n\t\t\tbreak;\n\t\tcommentsStarts.push_back(commentStarts);\n\t\tscanFrom = commentStarts + 4;\n\t}\n\t\/\/here we have a list of <!-- comments -->\n\twhile (commentsStarts.size() > 0) {\n\t\t\/\/get last comment\n\t\tchar* commentStarts = commentsStarts.back();\n\t\tcommentsStarts.pop_back();\n\t\tchar* commentEnds = strstr(commentStarts, "-->");\n\t\tint commentLength = (int)(commentEnds - commentStarts) + 3;\n\t\t\/\/shift text left\n\t\tmyStrcpy_s(commentStarts, pXP->dataSize - (int)(commentStarts - pXP->pData), commentStarts + commentLength);\n\t\tpXP->dataSize -= commentLength;\n\/\/mylog("======\\n%s----------\\n", pXP->pData);\n\t}\n\treturn 1;\n}\nbool XMLparser::nextTag(XMLparser* pXP) {\n\t\/\/returns 0 if no more tags, 1 - tag extracted\n\tchar* tagStarts = strstr(pXP->readFrom, "<");\n\tif (tagStarts == NULL)\n\t\treturn false;\n\tpXP->readFrom++;\n\tchar* tagEnds = strstr(pXP->readFrom, ">");\n\tif (tagEnds == NULL)\n\t\treturn false;\n\tpXP->readFrom = tagEnds + 1;\n\tpXP->tagLength = (int)(tagEnds - tagStarts) + 1;\n\tpXP->currentTag.assign(tagStarts, pXP->tagLength);\n\treturn true;\n} \nint XMLparser::nameEndsAt(std::string varName, std::string tag) {\n\tint scanFrom = 0;\n\tint nameLength = varName.length();\n\tstd::string optsBefore = "< ";\n\tstd::string optsAfter = " =\/>\\n";\n\twhile (1) {\n\t\tint varStartsAt = tag.find(varName, scanFrom);\n\t\tif (varStartsAt == std::string::npos)\n\t\t\treturn -1;\n\t\tscanFrom = varStartsAt + nameLength;\n\t\tchar charBefore = tag.at(varStartsAt - 1);\n\t\tif (optsBefore.find(charBefore) == std::string::npos)\n\t\t\tcontinue;\n\t\tchar charAfter = tag.at(scanFrom);\n\t\tif (optsAfter.find(charAfter) == std::string::npos)\n\t\t\tcontinue;\n\t\treturn scanFrom;\n\t}\n}\nint XMLparser::processSource(XMLparser* pXP) {\n\twhile (pXP->nextTag()) {\n\t\t\/\/extract tagName\n\t\tint nameStart = pXP->currentTag.find_first_not_of(" <");\n\t\tint nameEnd = pXP->currentTag.find_first_of(" =\/>\\n", nameStart+1);\n\t\tpXP->tagName = pXP->currentTag.substr(nameStart, (nameEnd - nameStart));\n\t\t\/\/open\/closed tag\n\t\tchar lastChar = pXP->currentTag.at(pXP->tagLength - 2);\n\t\tpXP->closedTag = (lastChar == '\/');\n\/\/mylog("[%s] [%s] closed=%d nameStart=%d nameEnd=%d\\n", pXP->currentTag.c_str(), pXP->tagName.c_str(), pXP->closedTag, nameStart, nameEnd);\n\t\tpXP->processTag();\n\t}\n\treturn 1;\n}\nstd::string XMLparser::buildFullPath(XMLparser* pXP, std::string filePath) {\n\tif (filePath.at(0) != '\/')\n\t\tfilePath = pXP->inAppFolder + filePath;\n\treturn (filesRoot + filePath);\n}\n\nstd::string XMLparser::getStringValue(std::string varName, std::string tag) {\n\t\/\/returns std::string\n\tint valueStartsAt = nameEndsAt(varName, tag);\n\tif (valueStartsAt < 0)\n\t\treturn ""; \/\/var not found\n\tvalueStartsAt = tag.find_first_not_of(" ", valueStartsAt);\n\tchar c = tag.at(valueStartsAt);\n\tif (c != '=')\n\t\treturn ""; \/\/var exists, but value not set\n\tvalueStartsAt = tag.find_first_not_of(" ", valueStartsAt + 1);\n\tc = tag.at(valueStartsAt);\n\tstd::string optsQuote = "\\"'";\n\tint valueEndsAt = 0;\n\tif (optsQuote.find(c) != std::string::npos) {\n\t\t\/\/the value is in quotes\n\t\tvalueStartsAt++;\n\t\tvalueEndsAt = tag.find(c, valueStartsAt);\n\t}\n\telse { \/\/value not quoted\n\t\tvalueEndsAt = tag.find_first_of(" \/>\\n", valueStartsAt);\n\t}\n\treturn tag.substr(valueStartsAt, valueEndsAt - valueStartsAt);\n}\n\nbool XMLparser::varExists(std::string varName, std::string tag) {\n\tint valueStartsAt = nameEndsAt(varName, tag);\n\tif (valueStartsAt < 0)\n\t\treturn false; \/\/var not found\n\treturn true;\n}\nint XMLparser::setCharsValue(char* pChars, int charsLength, std::string varName, std::string tag) {\n\tif (!varExists(varName, tag))\n\t\treturn 0; \/\/var not found\n\tstd::string val = getStringValue(varName, tag);\n\tmyStrcpy_s(pChars, charsLength, (char*)val.c_str());\n\treturn 1;\n}\nint XMLparser::setIntValue(int* pInt, std::string varName, std::string tag) {\n\tif (!varExists(varName, tag))\n\t\treturn 0; \/\/var not found\n\tstd::string val = getStringValue(varName, tag);\n\t*pInt = stoi(val);\n\treturn 1;\n}\nint XMLparser::setFloatValue(float* pFloat, std::string varName, std::string tag) {\n\tif (!varExists(varName, tag))\n\t\treturn 0; \/\/var not found\n\tstd::string val = getStringValue(varName, tag);\n\t*pFloat = stof(val);\n\treturn 1;\n}\nint XMLparser::setFloatArray(float* pFloats, int arrayLength, std::string varName, std::string tag) {\n\tif (!varExists(varName, tag))\n\t\treturn 0; \/\/var not found\n\tstd::string valuesString = getStringValue(varName, tag);\n\tstd::vector<std::string> valuesVector = splitString(valuesString, ",");\n\tint valsN = valuesVector.size();\n\tif (valsN == 1) {\n\t\tfloat val = stof(valuesVector.at(0));\n\t\tfor (int i = 0; i < arrayLength; i++)\n\t\t\tpFloats[i] = val;\n\t\treturn 1;\n\t}\n\tif (valsN != arrayLength) {\n\t\tmylog("ERROR in XMLparser::getFloatArray, %s, %s\\n", varName.c_str(), tag.c_str());\n\t\treturn -1;\n\t}\n\tfor (int i = 0; i < valsN; i++) {\n\t\tif (valuesVector.at(i).compare("x") != 0)\n\t\t\tpFloats[i] = stof(valuesVector.at(i));\n\t}\n\treturn 1;\n}int XMLparser::setIntArray(int* pInts, int arrayLength, std::string varName, std::string tag) {\n\tif (!varExists(varName, tag))\n\t\treturn 0; \/\/var not found\n\tstd::string valuesString = getStringValue(varName, tag);\n\tstd::vector<std::string> valuesVector = splitString(valuesString, ",");\n\tint valsN = valuesVector.size();\n\tif (valsN == 1) {\n\t\tint val = stoi(valuesVector.at(0));\n\t\tfor (int i = 0; i < arrayLength; i++)\n\t\t\tpInts[i] = val;\n\t\treturn 1;\n\t}\n\tif (valsN != arrayLength) {\n\t\tmylog("ERROR in XMLparser::getIntArray, %s, %s\\n", varName.c_str(), tag.c_str());\n\t\treturn -1;\n\t}\n\tfor (int i = 0; i < valsN; i++) {\n\t\tif(valuesVector.at(i).compare("x") != 0)\n\t\t\tpInts[i] = stoi(valuesVector.at(i));\n\t}\n\treturn 1;\n}\nint XMLparser::setUintColorValue(unsigned int* pInt, std::string varName, std::string tag) {\n\tif (!varExists(varName, tag))\n\t\treturn 0; \/\/var not found\n\tMyColor clr;\n\tstd::string val = getStringValue(varName, tag);\n\tif (val.at(0) == '#') {\n\t\t\/\/the value is in HTML HEX format (like #ff0000)\n\t\tint r = std::stoi(val.substr(1, 2), nullptr, 16);\n\t\tint g = std::stoi(val.substr(3, 2), nullptr, 16);\n\t\tint b = std::stoi(val.substr(5, 2), nullptr, 16);\n\t\tint a = 255;\n\t\tif (val.size() > 7)\n\t\t\ta = std::stoi(val.substr(7, 2), nullptr, 16);\n\t\tclr.setRGBA(r, g, b, a);\n\t}\n\telse if (val.find(",") > 0) {\n\t\t\/\/the value is an array of ints (?)\n\t\tstd::vector<std::string> valuesVector = splitString(val, ",");\n\t\tint r = std::stoi(valuesVector[0]);\n\t\tint g = std::stoi(valuesVector[1]);\n\t\tint b = std::stoi(valuesVector[2]);\n\t\tint a = 255;\n\t\tif (valuesVector.size() > 3)\n\t\t\ta = std::stoi(valuesVector[3]);\n\t\tclr.setRGBA(r, g, b, a);\n\t}\n\telse {\n\t\tmylog("ERROR in XMLparser::setUintColorValue: unhandled Color format %s\\n",tag.c_str());\n\t\treturn -1;\n\t}\n\t*pInt = clr.getUint32();\n\treturn 1;\n}\nint XMLparser::setIntBoolValue(int* pInt, std::string varName, std::string tag) {\n\tif (!varExists(varName, tag))\n\t\treturn 0; \/\/var not found\n\tstd::string val = getStringValue(varName, tag);\n\tif (val.compare("") == 0) *pInt = 1;\n\telse if (val.compare("1") == 0) *pInt = 1;\n\telse if (val.compare("0") == 0) *pInt = 0;\n\telse if (val.compare("yes") == 0) *pInt = 1;\n\telse if (val.compare("no") == 0) *pInt = 0;\n\telse if (val.compare("true") == 0) *pInt = 1;\n\telse if (val.compare("false") == 0) *pInt = 0;\n\telse {\n\t\tmylog("ERROR in XMLparser::setIntBoolValue, %s=%s in %s\\n",varName.c_str(),val.c_str(),tag.c_str());\n\t\treturn -1;\n\t}\n\treturn 1;\n}\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#include "ModelBuilder1base.h"\n#include "platform.h"\n#include "utils.h"\n#include "DrawJob.h"\n#include "Shader.h"\n\nextern float degrees2radians;\n\nModelBuilder1base::~ModelBuilder1base() {\n\treleaseGroup(this);\n\n\t\/\/clear all vectors\n\tint itemsN = vertices.size();\n\tfor (int i = 0; i < itemsN; i++)\n\t\tdelete vertices.at(i);\n\tvertices.clear();\n\n\titemsN = triangles.size();\n\tfor (int i = 0; i < itemsN; i++)\n\t\tdelete triangles.at(i);\n\ttriangles.clear();\n\n\titemsN = vShapesStack.size();\n\tfor (int i = 0; i < itemsN; i++)\n\t\tdelete vShapesStack.at(i);\n\tvShapesStack.clear();\n\n\titemsN = groupsStack.size();\n\tfor (int i = 0; i < itemsN; i++)\n\t\tdelete groupsStack.at(i);\n\tgroupsStack.clear();\n\tif (pCurrentGroup != NULL)\n\t\tdelete pCurrentGroup;\n\tif (pLastClosedGroup != NULL)\n\t\tdelete pLastClosedGroup;\n\n\titemsN = materialsList.size();\n\tfor (int i = 0; i < itemsN; i++)\n\t\tdelete materialsList.at(i);\n\tmaterialsList.clear();\n\n\tsubjNumbersList.clear();\n}\nint ModelBuilder1base::useSubjN(ModelBuilder1base* pMB, int subjN) {\n\tpMB->usingSubjN = subjN;\n\tint itemsN = pMB->subjNumbersList.size();\n\tbool newN = true;\n\tif (itemsN > 0)\n\t\tfor (int i = 0; i < itemsN; i++)\n\t\t\tif (pMB->subjNumbersList.at(i) == subjN) {\n\t\t\t\tnewN = false;\n\t\t\t\tbreak;\n\t\t\t}\n\tif (newN)\n\t\tpMB->subjNumbersList.push_back(subjN);\n\treturn subjN;\n}\nint ModelBuilder1base::useMaterial(ModelBuilder1base* pMB, Material* pMT) {\n\tint itemsN = pMB->materialsList.size();\n\tif (itemsN > 0)\n\t\tfor (int i = 0; i < itemsN; i++)\n\t\t\tif (memcmp(pMB->materialsList.at(i), pMT, sizeof(Material)) == 0) {\n\t\t\t\tpMB->usingMaterialN = i;\n\t\t\t\treturn i;\n\t\t\t}\n\t\/\/if here - add new material to the list\n\tpMB->usingMaterialN = itemsN;\n\t\/\/create a copy of new Material and add to the list\n\tMaterial* pMTnew = new Material(*pMT);\n\tpMB->materialsList.push_back(pMTnew);\n\treturn itemsN;\n}\nint ModelBuilder1base::add2triangles(ModelBuilder1base* pMB, int nNW, int nNE, int nSW, int nSE, int n) {\n\t\/\/indexes: NorthWest, NorthEast, SouthWest,SouthEast\n\tif (n % 2 == 0) { \/\/even number\n\t\taddTriangle(pMB, nNW, nSW, nNE);\n\t\taddTriangle(pMB, nNE, nSW, nSE);\n\t}\n\telse { \/\/odd number\n\t\taddTriangle(pMB, nNW, nSE, nNE);\n\t\taddTriangle(pMB, nNW, nSW, nSE);\n\t}\n\treturn pMB->triangles.size() - 1;\n}\nint ModelBuilder1base::addTriangle(ModelBuilder1base* pMB, int i0, int i1, int i2) {\n\tTriangle01* pTR = new Triangle01();\n\tpMB->triangles.push_back(pTR);\n\tpTR->idx[0] = i0;\n\tpTR->idx[1] = i1;\n\tpTR->idx[2] = i2;\n\tpTR->subjN = pMB->usingSubjN;\n\tpTR->materialN = pMB->usingMaterialN;\n\t\/\/mark\n\tif (pMB->pCurrentGroup != NULL)\n\t\tif (strcmp(pMB->pCurrentGroup->marks, "") != 0)\n\t\t\tmyStrcpy_s(pTR->marks, 124, pMB->pCurrentGroup->marks);\n\treturn pMB->triangles.size() - 1;\n}\nint ModelBuilder1base::addVertex(ModelBuilder1base* pMB, float kx, float ky, float kz, float nx, float ny, float nz) {\n\tVertex01* pVX = new Vertex01();\n\tpMB->vertices.push_back(pVX);\n\tpVX->aPos[0] = kx;\n\tpVX->aPos[1] = ky;\n\tpVX->aPos[2] = kz;\n\t\/\/normal\n\tpVX->aNormal[0] = nx;\n\tpVX->aNormal[1] = ny;\n\tpVX->aNormal[2] = nz;\n\tpVX->subjN = pMB->usingSubjN;\n\tpVX->materialN = pMB->usingMaterialN;\n\t\/\/mark\n\tif (pMB->pCurrentGroup != NULL)\n\t\tif (strcmp(pMB->pCurrentGroup->marks, "") != 0)\n\t\t\tmyStrcpy_s(pVX->marks, 124, pMB->pCurrentGroup->marks);\n\n\treturn pMB->vertices.size() - 1;\n}\nint ModelBuilder1base::buildDrawJobs(ModelBuilder1base* pMB, std::vector<GameSubj*> gameSubjs) {\n\tint totalSubjsN = pMB->subjNumbersList.size();\n\tif (totalSubjsN < 1) {\n\t\tpMB->subjNumbersList.push_back(-1);\n\t\ttotalSubjsN = 1;\n\t}\n\tint totalMaterialsN = pMB->materialsList.size();\n\tif (totalSubjsN < 2 && totalMaterialsN < 2) {\n\t\t\/\/simple single DrawJob\n\t\tMaterial* pMT = pMB->materialsList.at(0);\n\t\tGameSubj* pGS = NULL;\n\t\tint gsN = pMB->subjNumbersList.at(0);\n\t\tif (gsN >= 0)\n\t\t\tpGS = gameSubjs.at(gsN);\n\t\tif (pGS != NULL)\n\t\t\tpGS->djStartN = DrawJob::drawJobs.size();\n\t\tbuildSingleDrawJob(pMT, pMB->vertices, pMB->triangles);\n\t\tif (pGS != NULL)\n\t\t\tpGS->djTotalN = DrawJob::drawJobs.size() - pGS->djStartN;\n\t\treturn 1;\n\t}\n\tint totalVertsN = pMB->vertices.size();\n\tint totalTrianglesN = pMB->triangles.size();\n\t\/\/clear flags\n\tfor (int vN = 0; vN < totalVertsN; vN++) {\n\t\tVertex01* pVX = pMB->vertices.at(vN);\n\t\tpVX->flag = 0;\n\t}\n\tfor (int tN = 0; tN < totalTrianglesN; tN++) {\n\t\tTriangle01* pTR = pMB->triangles.at(tN);\n\t\tpTR->flag = 0;\n\t}\n\tint addedDJs = 0;\n\tfor (int sN = 0; sN < totalSubjsN; sN++) {\n\t\tGameSubj* pGS = NULL;\n\t\tint gsN = pMB->subjNumbersList.at(sN);\n\t\tif (gsN >= 0)\n\t\t\tpGS = gameSubjs.at(gsN);\n\t\tif (pGS != NULL)\n\t\t\tpGS->djStartN = DrawJob::drawJobs.size();\n\t\tfor (int mtN = 0; mtN < totalMaterialsN; mtN++) {\n\t\t\tMaterial* pMT = pMB->materialsList.at(mtN);\n\t\t\tstd::vector<Vertex01*> useVertices;\n\t\t\tstd::vector<Triangle01*> useTriangles;\n\t\t\tfor (int vN = 0; vN < totalVertsN; vN++) {\n\t\t\t\tVertex01* pVX = pMB->vertices.at(vN);\n\t\t\t\tif (pVX->flag != 0)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (pVX->subjN != gsN)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (pVX->materialN != mtN)\n\t\t\t\t\tcontinue;\n\t\t\t\t\/\/if here - make a copy\n\t\t\t\tVertex01* pVX2 = new Vertex01(*pVX);\n\t\t\t\tuseVertices.push_back(pVX2);\n\t\t\t\tpVX2->altN = vN;\n\t\t\t\tpVX->flag = 1;\n\t\t\t\tif (pVX->endOfSequence > 0) {\n\t\t\t\t\trearrangeArraysForDrawJob(pMB, pMB->vertices, useVertices, useTriangles);\n\t\t\t\t\tbuildSingleDrawJob(pMT, useVertices, useTriangles);\n\t\t\t\t\taddedDJs++;\n\t\t\t\t\t\/\/clear and proceed to next sequence\n\t\t\t\t\tint useVerticesN = useVertices.size();\n\t\t\t\t\tfor (int i = 0; i < useVerticesN; i++)\n\t\t\t\t\t\tdelete useVertices.at(i);\n\t\t\t\t\tuseVertices.clear();\n\t\t\t\t}\n\t\t\t}\n\t\t\tint useVerticesN = useVertices.size();\n\t\t\tif (useVerticesN < 1)\n\t\t\t\tcontinue; \/\/to next material\n\t\t\t\/\/pick triangles\n\t\t\tfor (int tN = 0; tN < totalTrianglesN; tN++) {\n\t\t\t\tTriangle01* pTR = pMB->triangles.at(tN);\n\t\t\t\tif (pTR->flag != 0)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (pTR->subjN != gsN)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (pTR->materialN != mtN)\n\t\t\t\t\tcontinue;\n\t\t\t\t\/\/if here - make a copy\n\t\t\t\tTriangle01* pTR2 = new Triangle01(*pTR);\n\t\t\t\tuseTriangles.push_back(pTR2);\n\t\t\t\tpTR->flag = 1;\n\t\t\t}\n\t\t\trearrangeArraysForDrawJob(pMB, pMB->vertices, useVertices, useTriangles);\n\t\t\tbuildSingleDrawJob(pMT, useVertices, useTriangles);\n\t\t\taddedDJs++;\n\t\t\t\/\/clear all for next material\n\t\t\tfor (int i = 0; i < useVerticesN; i++)\n\t\t\t\tdelete useVertices.at(i);\n\t\t\tuseVertices.clear();\n\t\t\tint useTrianglesN = useTriangles.size();\n\t\t\tfor (int i = 0; i < useTrianglesN; i++)\n\t\t\t\tdelete useTriangles.at(i);\n\t\t\tuseTriangles.clear();\n\t\t}\n\t\tif (pGS != NULL)\n\t\t\tpGS->djTotalN = DrawJob::drawJobs.size() - pGS->djStartN;\n\t}\n\treturn addedDJs;\n}\n\nint ModelBuilder1base::buildSingleDrawJob(Material* pMT, std::vector<Vertex01*> useVertices, std::vector<Triangle01*> useTriangles) {\n\tint totalVertsN = useVertices.size();\n\tif (totalVertsN < 1)\n\t\treturn 0;\n\tif (pMT->uTex2nm >= 0)\n\t\tcalculateTangentSpace(useVertices, useTriangles);\n\tpMT->pickShaderNumber();\n\tDrawJob* pDJ = new DrawJob();\n\t\/\/copy material to DJ\n\tmemcpy(&pDJ->mt, pMT, sizeof(Material));\n\t\/\/calculate VBO element size (stride) and variables offsets in VBO\n\tint VBOid = DrawJob::newBufferId();\n\tint stride = 0;\n\tpDJ->setDesirableOffsets(&stride, pDJ->mt.shaderN, VBOid);\n\t\/\/create an array for VBO\n\tint bufferSize = totalVertsN * stride;\n\tfloat* vertsBuffer = new float[bufferSize];\n\t\/\/fill vertsBuffer\n\tShader* pSh = Shader::shaders.at(pDJ->mt.shaderN);\n\tint floatSize = sizeof(float);\n\tfor (int vN = 0; vN < totalVertsN; vN++) {\n\t\tVertex01* pVX = useVertices.at(vN);\n\t\tint idx = vN * stride \/ floatSize;\n\t\t\/\/pick data from vertex and move to the buffer\n\t\tmemcpy(&vertsBuffer[idx + pDJ->aPos.offset \/ floatSize], pVX->aPos, 3 * floatSize);\n\t\tif (pSh->l_aNormal >= 0) \/\/normal\n\t\t\tmemcpy(&vertsBuffer[idx + pDJ->aNormal.offset \/ floatSize], pVX->aNormal, 3 * floatSize);\n\t\tif (pSh->l_aTuv >= 0) \/\/attribute TUV (texture coordinates)\n\t\t\tmemcpy(&vertsBuffer[idx + pDJ->aTuv.offset \/ floatSize], pVX->aTuv, 2 * floatSize);\n\t\tif (pSh->l_aTuv2 >= 0) \/\/attribute TUV2 (normal maps)\n\t\t\tmemcpy(&vertsBuffer[idx + pDJ->aTuv2.offset \/ floatSize], pVX->aTuv2, 2 * floatSize);\n\t\tif (pSh->l_aTangent >= 0)\n\t\t\tmemcpy(&vertsBuffer[idx + pDJ->aTangent.offset \/ floatSize], pVX->aTangent, 3 * floatSize);\n\t\tif (pSh->l_aBinormal >= 0)\n\t\t\tmemcpy(&vertsBuffer[idx + pDJ->aBinormal.offset \/ floatSize], pVX->aBinormal, 3 * floatSize);\n\t}\n\t\/\/buffer is ready, create VBO\n\tglBindBuffer(GL_ARRAY_BUFFER, VBOid);\n\tglBufferData(GL_ARRAY_BUFFER, bufferSize * floatSize, vertsBuffer, GL_STATIC_DRAW);\n\tdelete[] vertsBuffer;\n\tpDJ->pointsN = totalVertsN;\n\n\tint totalTrianglesN = useTriangles.size();\n\tif (totalTrianglesN > 0) {\n\t\t\/\/create EBO\n\t\tint totalIndexesN = totalTrianglesN * 3;\n\t\t\/\/create buffer\n\t\tGLushort* indexBuffer = new GLushort[totalIndexesN];\n\t\tfor (int tN = 0; tN < totalTrianglesN; tN++) {\n\t\t\tTriangle01* pTR = useTriangles[tN];\n\t\t\tint idx = tN * 3;\n\t\t\tindexBuffer[idx] = (GLushort)pTR->idx[0];\n\t\t\tindexBuffer[idx + 1] = (GLushort)pTR->idx[1];\n\t\t\tindexBuffer[idx + 2] = (GLushort)pTR->idx[2];\n\t\t}\n\t\t\/\/buffer is ready, create IBO\n\t\tpDJ->glEBOid = DrawJob::newBufferId();\n\t\tglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pDJ->glEBOid);\n\t\tglBufferData(GL_ELEMENT_ARRAY_BUFFER, totalIndexesN * sizeof(GLushort), indexBuffer, GL_STATIC_DRAW);\n\t\tdelete[] indexBuffer;\n\t\tpDJ->pointsN = totalIndexesN;\n\t}\n\t\/\/create and fill vertex attributes array (VAO)\n\tpDJ->buildVAO();\n\treturn 1;\n}\n\nint ModelBuilder1base::rearrangeArraysForDrawJob(ModelBuilder1base* pMB, std::vector<Vertex01*> allVertices, std::vector<Vertex01*> useVertices, std::vector<Triangle01*> useTriangles) {\n\tint totalTrianglesN = useTriangles.size();\n\tif (totalTrianglesN < 1)\n\t\treturn 0;\n\tint totalVerticesN = useVertices.size();\n\t\/\/save new vertices order in original vertices array\n\t\/\/since triangles indices refer to original vertices order\n\tfor (int i = 0; i < totalVerticesN; i++) {\n\t\tVertex01* pVX1 = useVertices.at(i);\n\t\tVertex01* pVX0 = allVertices.at(pVX1->altN);\n\t\tpVX0->altN = i;\n\t}\n\t\/\/replace triangle original indices by new numbers saved in original vertices altN\n\tfor (int tN = 0; tN < totalTrianglesN; tN++) {\n\t\tTriangle01* pTR = useTriangles.at(tN);\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tVertex01* pVX0 = allVertices.at(pTR->idx[i]);\n\t\t\tpTR->idx[i] = pVX0->altN;\n\t\t}\n\t}\n\treturn 1;\n}\n\nint ModelBuilder1base::moveGroupDg(ModelBuilder1base* pMB, float aX, float aY, float aZ, float kX, float kY, float kZ) {\n\t\/\/moves and rotates vertex group\n\t\/\/rotation angles are set in degrees\n\tmat4x4 transformMatrix = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };\n\tmat4x4_translate(transformMatrix, kX, kY, kZ);\n\t\/\/rotation order: Z-X-Y\n\tif (aY != 0) mat4x4_rotate_Y(transformMatrix, transformMatrix, degrees2radians * aY);\n\tif (aX != 0) mat4x4_rotate_X(transformMatrix, transformMatrix, degrees2radians * aX);\n\tif (aZ != 0) mat4x4_rotate_Z(transformMatrix, transformMatrix, degrees2radians * aZ);\n\n\tint vertsN = pMB->vertices.size();\n\tfor (int i = pMB->pCurrentGroup->fromVertexN; i < vertsN; i++) {\n\t\tVertex01* pVX = pMB->vertices.at(i);\n\t\tmat4x4_mul_vec4plus(pVX->aPos, transformMatrix, pVX->aPos, 1);\n\t\tmat4x4_mul_vec4plus(pVX->aNormal, transformMatrix, pVX->aNormal, 0);\n\t}\n\treturn 1;\n}\n\nint ModelBuilder1base::calculateTangentSpace(std::vector<Vertex01*> useVertices, std::vector<Triangle01*> useTriangles) {\n\tint totalVertsN = useVertices.size();\n\tif (totalVertsN < 1)\n\t\treturn 0;\n\tint totalTrianglesN = useTriangles.size();\n\t\/\/assuming that GL_TRIANGLES\n\t\/\/clear flags\n\tfor (int vN = 0; vN < totalVertsN; vN++) {\n\t\tVertex01* pV = useVertices.at(vN);\n\t\tpV->flag = 0;\n\t}\n\tfor (int vN = 0; vN < totalVertsN; vN++) {\n\t\tVertex01* pVX = useVertices.at(vN);\n\t\tif (pVX->flag != 0)\n\t\t\tcontinue;\n\t\tTriangle01* pT = NULL;\n\t\tfor (int tN = 0; tN < totalTrianglesN; tN++) {\n\t\t\tpT = useTriangles.at(tN);\n\t\t\tbool haveTriangle = false;\n\t\t\tfor (int i = 0; i < 3; i++)\n\t\t\t\tif (pT->idx[i] == vN) {\n\t\t\t\t\thaveTriangle = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif (haveTriangle)\n\t\t\t\tbreak;\n\t\t}\n\t\tVertex01* pV[3];\n\t\tfor (int i = 0; i < 3; i++)\n\t\t\tpV[i] = useVertices.at(pT->idx[i]);\n\n\t\tfloat dPos1[3];\n\t\tfloat dPos2[3];\n\t\tfloat dUV1[2];\n\t\tfloat dUV2[2];\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tdPos1[i] = pV[1]->aPos[i] - pV[0]->aPos[i];\n\t\t\tdPos2[i] = pV[2]->aPos[i] - pV[0]->aPos[i];\n\t\t}\n\t\tfor (int i = 0; i < 2; i++) {\n\t\t\tdUV1[i] = pV[1]->aTuv2[i] - pV[0]->aTuv2[i];\n\t\t\tdUV2[i] = pV[2]->aTuv2[i] - pV[0]->aTuv2[i];\n\t\t}\n\n\t\tfloat tangent[3];\n\t\tfloat binormal[3];\n\t\tfloat divider = dUV1[0] * dUV2[1] - dUV1[1] * dUV2[0];\n\t\tif (divider == 0) {\n\t\t\tv3set(tangent, 1, 0, 0);\n\t\t\tv3set(binormal, 0, -1, 0);\n\t\t}\n\t\telse {\n\t\t\tfloat r = 1.0f \/ divider;\n\t\t\tfor (int i = 0; i < 3; i++) {\n\t\t\t\ttangent[i] = (dPos1[i] * dUV2[1] - dPos2[i] * dUV1[1]) * r;\n\t\t\t\tbinormal[i] = -(dPos2[i] * dUV1[0] - dPos1[i] * dUV2[0]) * r;\n\t\t\t}\n\t\t\tvec3_norm(tangent, tangent);\n\t\t\tvec3_norm(binormal, binormal);\n\t\t}\n\t\t\/\/add to all 3 vertices\n\t\tfor (int n = 0; n < 3; n++) {\n\t\t\tif (pV[n]->flag > 0)\n\t\t\t\tcontinue;\n\t\t\tv3copy(pV[n]->aTangent, tangent);\n\t\t\tv3copy(pV[n]->aBinormal, binormal);\n\t\t\tpV[n]->flag = 1;\n\t\t}\n\t}\n\t\/\/normalize tangent and binormal around normal\n\tfor (int vN = 0; vN < totalVertsN; vN++) {\n\t\tVertex01* pV = useVertices.at(vN);\n\t\tfloat v3out[3];\n\t\t\/\/tangent\n\t\tvec3_mul_cross(v3out, pV->aNormal, pV->aBinormal);\n\t\tif (v3dotProduct(pV->aTangent, v3out) < 0)\n\t\t\tv3inverse(v3out);\n\t\tv3copy(pV->aTangent, v3out);\n\t\t\/\/binormal\n\t\tvec3_mul_cross(v3out, pV->aNormal, pV->aTangent);\n\t\tif (v3dotProduct(pV->aBinormal, v3out) < 0)\n\t\t\tv3inverse(v3out);\n\t\tv3copy(pV->aBinormal, v3out);\n\t}\n\treturn 1;\n}\nvoid ModelBuilder1base::lockGroup(ModelBuilder1base* pMB) {\n\tGroup01* pPrevGroup = pMB->pCurrentGroup;\n\tif (pMB->pCurrentGroup != NULL)\n\t\tpMB->groupsStack.push_back(pMB->pCurrentGroup);\n\tpMB->pCurrentGroup = new Group01();\n\tpMB->pCurrentGroup->fromVertexN = pMB->vertices.size();\n\tpMB->pCurrentGroup->fromTriangleN = pMB->triangles.size();\n\t\/\/marks\n\tif(pPrevGroup != NULL)\n\t\tif (strcmp(pPrevGroup->marks, "") != 0)\n\t\t\tmyStrcpy_s(pMB->pCurrentGroup->marks, 124, pPrevGroup->marks);\n}\nvoid ModelBuilder1base::releaseGroup(ModelBuilder1base* pMB) {\n\tif (pMB->pLastClosedGroup != NULL)\n\t\tdelete pMB->pLastClosedGroup;\n\tpMB->pLastClosedGroup = pMB->pCurrentGroup;\n\n\tif (pMB->groupsStack.size() > 0) {\n\t\tpMB->pCurrentGroup = pMB->groupsStack.back();\n\t\tpMB->groupsStack.pop_back();\n\t}\n\telse\n\t\tpMB->pCurrentGroup = NULL;\n}\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#pragma once\n#include "XMLparser.h"\n#include "ModelBuilder.h"\n#include "GroupTransform.h"\n\nclass ModelLoader : public XMLparser\n{\npublic:\n\tModelBuilder* pModelBuilder = NULL;\n\tbool ownModelBuilder = false;\n\tstd::vector<GameSubj*>* pSubjsVector = NULL;\npublic:\n\tModelLoader(std::vector<GameSubj*>* pSubjsVector0, int subjN, ModelBuilder* pMB, std::string filePath) : XMLparser(filePath) {\n\t\tpSubjsVector = pSubjsVector0;\n\t\tif (pMB != NULL) {\n\t\t\townModelBuilder = false;\n\t\t\tpModelBuilder = pMB;\n\t\t}\n\t\telse {\n\t\t\townModelBuilder = true;\n\t\t\tpModelBuilder = new ModelBuilder();\n\t\t\tpModelBuilder->lockGroup(pModelBuilder);\n\t\t}\n\t\tpModelBuilder->useSubjN(subjN);\n\t};\n\tvirtual ~ModelLoader() {\n\t\tif (!ownModelBuilder)\n\t\t\treturn;\n\t\tpModelBuilder->buildDrawJobs(*pSubjsVector);\n\t\tdelete pModelBuilder;\n\t};\n\tstatic int processTag_a(ModelLoader* pML); \/\/apply\n\tstatic int setValueFromIntHashMap(int* pInt, std::map<std::string, int> intHashMap, std::string varName, std::string tagStr);\n\tstatic int setTexture(ModelLoader* pML, int* pInt, std::string txName);\n\tstatic int setMaterialTextures(ModelLoader* pML, Material* pMT);\n\tstatic int fillProps_vs(VirtualShape* pVS, std::string tagStr); \/\/virtual shape\n\tstatic int fillProps_mt(Material* pMT, std::string tagStr, ModelLoader* pML); \/\/Material\n\tstatic int fillProps_gt(GroupTransform* pGS, ModelBuilder* pMB, std::string tagStr);\n\tint processTag() { return processTag(this); };\n\tstatic int processTag(ModelLoader* pML);\n\tstatic int loadModel(std::vector<GameSubj*>* pSubjsVector0, std::string sourceFile, std::string subjClass);\n\tstatic int processTag_clone(ModelLoader* pML);\n\tstatic int addMark(char* marks, std::string newMark);\n\tstatic int processTag_do(ModelLoader* pML);\n};\n\n<\/pre><\/div>\n\n\n
\n\n\n\n\n#include "ModelLoader.h"\n#include "platform.h"\n#include "TheGame.h"\n#include "DrawJob.h"\n#include "Texture.h"\n#include "utils.h"\n\nextern TheGame theGame;\n\nint ModelLoader::loadModel(std::vector<GameSubj*>* pSubjsVector0, std::string sourceFile, std::string subjClass) {\n\t\/\/returns element's (Subj) number or -1\n\tint subjN = pSubjsVector0->size();\n\tGameSubj* pGS = theGame.newGameSubj(subjClass);\n\tpSubjsVector0->push_back(pGS);\n\t\/\/pGS->djStartN = DrawJob::drawJobs.size();\n\tModelLoader* pML = new ModelLoader(pSubjsVector0, subjN, NULL, sourceFile);\n\tprocessSource(pML);\n\tdelete pML;\n\t\/\/pGS->djTotalN = DrawJob::drawJobs.size() - pGS->djStartN;\n\treturn subjN;\n}\nint ModelLoader::setValueFromIntHashMap(int* pInt, std::map<std::string, int> intHashMap, std::string varName, std::string tagStr) {\n\tif (!varExists(varName, tagStr))\n\t\treturn 0;\n\tstd::string str0 = getStringValue(varName, tagStr);\n\tif (intHashMap.find(str0) == intHashMap.end()) {\n\t\tmylog("ERROR in ModelLoader::setValueFromIntMap, %s not found, %s\\n", varName.c_str(), tagStr.c_str());\n\t\treturn -1;\n\t}\n\t*pInt = intHashMap[getStringValue(varName, tagStr)];\n\treturn 1;\n}\nint ModelLoader::setTexture(ModelLoader* pML, int* pInt, std::string txName) {\n\tModelBuilder* pMB = pML->pModelBuilder;\n\tstd::string varName = txName + "_use";\n\tif (setValueFromIntHashMap(pInt, pMB->texturesHashMap, varName, pML->currentTag) == 0) {\n\t\t\/\/the texture is not in hash table\n\t\tvarName = txName + "_src";\n\t\tif (varExists(varName, pML->currentTag)) {\n\t\t\tstd::string txFile = getStringValue(varName, pML->currentTag);\n\t\t\tvarName = txName + "_ckey";\n\t\t\tunsigned int intCkey = 0;\n\t\t\tsetUintColorValue(&intCkey, varName, pML->currentTag);\n\t\t\t*pInt = Texture::loadTexture(buildFullPath(pML, txFile), intCkey);\n\t\t}\n\t}\n\treturn 1;\n}\nint ModelLoader::setMaterialTextures(ModelLoader* pML, Material* pMT) {\n\tsetTexture(pML, &pMT->uTex0, "uTex0");\n\tsetTexture(pML, &pMT->uTex1mask, "uTex1mask");\n\tsetTexture(pML, &pMT->uTex2nm, "uTex2nm");\n\tsetTexture(pML, &pMT->uTex3, "uTex3");\n\treturn 1;\n}\nint ModelLoader::fillProps_mt(Material* pMT, std::string tagStr, ModelLoader* pML) {\n\tsetCharsValue(pMT->shaderType, 20, "mt_type", tagStr);\n\tsetMaterialTextures(pML, pMT);\n\t\/\/color\n\tif (varExists("uColor", tagStr)) {\n\t\tunsigned int uintColor = 0;\n\t\tsetUintColorValue(&uintColor, "uColor", tagStr);\n\t\tpMT->uColor.setUint32(uintColor);\n\t}\n\t\/\/mylog("mt.uTex0=%d, mt.uTex1mask=%d\\n", mt.uTex0, mt.uTex1mask);\n\tif (varExists("primitiveType", tagStr)) {\n\t\tstd::string str0 = getStringValue("primitiveType", tagStr);\n\t\tif (str0.compare("GL_POINTS") == 0) pMT->primitiveType = GL_POINTS;\n\t\telse if (str0.compare("GL_LINES") == 0) pMT->primitiveType = GL_LINES;\n\t\telse if (str0.compare("GL_LINE_STRIP") == 0) pMT->primitiveType = GL_LINE_STRIP;\n\t\telse if (str0.compare("GL_LINE_LOOP") == 0) pMT->primitiveType = GL_LINE_LOOP;\n\t\telse if (str0.compare("GL_TRIANGLE_STRIP") == 0) pMT->primitiveType = GL_TRIANGLE_STRIP;\n\t\telse if (str0.compare("GL_TRIANGLE_FAN") == 0) pMT->primitiveType = GL_TRIANGLE_FAN;\n\t\telse pMT->primitiveType = GL_TRIANGLES;\n\t}\n\tsetIntValue(&pMT->uTex1alphaChannelN, "uTex1alphaChannelN", tagStr);\n\tsetIntValue(&pMT->uTex0translateChannelN, "uTex0translateChannelN", tagStr);\n\tsetIntBoolValue(&pMT->uAlphaBlending, "uAlphaBlending", tagStr);\n\tsetFloatValue(&pMT->uAlphaFactor, "uAlphaFactor", tagStr);\n\tsetFloatValue(&pMT->uAmbient, "uAmbient", tagStr);\n\tsetFloatValue(&pMT->uSpecularIntencity, "uSpecularIntencity", tagStr);\n\tsetFloatValue(&pMT->uSpecularMinDot, "uSpecularMinDot", tagStr);\n\tsetFloatValue(&pMT->uSpecularPowerOf, "uSpecularPowerOf", tagStr);\n\n\tpML->pModelBuilder->useMaterial(pMT);\n\treturn 1;\n}\nint ModelLoader::processTag(ModelLoader* pML) {\n\tModelBuilder* pMB = pML->pModelBuilder;\n\tif (pML->tagName.compare("texture_as") == 0) {\n\t\t\/\/saves texture N in texturesMap under given name\n\t\tstd::string keyName = getStringValue("texture_as", pML->currentTag);\n\t\tif (pMB->texturesHashMap.find(keyName) != pMB->texturesHashMap.end())\n\t\t\treturn pMB->texturesHashMap[keyName];\n\t\telse { \/\/add new\n\t\t\tstd::string txFile = getStringValue("src", pML->currentTag);\n\t\t\tunsigned int intCkey = 0;\n\t\t\tsetUintColorValue(&intCkey, "ckey", pML->currentTag);\n\t\t\tint txN = Texture::loadTexture(buildFullPath(pML, txFile), intCkey);\n\t\t\tpMB->texturesHashMap[keyName] = txN;\n\t\t\t\/\/mylog("%s=%d\\n", keyName.c_str(), pMB->texturesMap[keyName]);\n\t\t\treturn txN;\n\t\t}\n\t}\n\tif (pML->tagName.find("mt_") == 0) {\n\t\t\/\/sets current material\n\t\tModelBuilder* pMB = pML->pModelBuilder;\n\t\tif (!pML->closedTag) {\n\t\t\t\/\/save previous material in stack\n\t\t\tif (pMB->usingMaterialN >= 0)\n\t\t\t\tpMB->materialsStack.push_back(pMB->usingMaterialN);\n\t\t}\n\t\tMaterial mt;\n\t\treturn fillProps_mt(&mt, pML->currentTag, pML);\n\t}\n\tif (pML->tagName.find("\/mt_") == 0) {\n\t\t\/\/restore previous material\n\t\tif (pMB->materialsStack.size() > 0) {\n\t\t\tpMB->usingMaterialN = pMB->materialsStack.back();\n\t\t\tpMB->materialsStack.pop_back();\n\t\t}\n\t\treturn 1;\n\t}\n\tif (pML->tagName.compare("vs") == 0) {\n\t\t\/\/sets virtual shape\n\t\tModelBuilder* pMB = pML->pModelBuilder;\n\t\tif (pML->closedTag) {\n\t\t\tif (pMB->pCurrentVShape != NULL)\n\t\t\t\tdelete pMB->pCurrentVShape;\n\t\t}\n\t\telse { \/\/open tag\n\t\t\t\/\/save previous vshape in stack\n\t\t\tif (pMB->pCurrentVShape != NULL)\n\t\t\t\tpMB->vShapesStack.push_back(pMB->pCurrentVShape);\n\t\t}\n\t\tpMB->pCurrentVShape = new VirtualShape();\n\t\tfillProps_vs(pMB->pCurrentVShape, pML->currentTag);\n\t\treturn 1;\n\t}\n\tif (pML->tagName.compare("\/vs") == 0) {\n\t\t\/\/restore previous virtual shape\n\t\tif (pMB->vShapesStack.size() > 0) {\n\t\t\tif (pMB->pCurrentVShape != NULL)\n\t\t\t\tdelete(pMB->pCurrentVShape);\n\t\t\tpMB->pCurrentVShape = pMB->vShapesStack.back();\n\t\t\tpMB->vShapesStack.pop_back();\n\t\t}\n\t\treturn 1;\n\t}\n\tif (pML->tagName.compare("group") == 0) {\n\t\tstd::string notAllowed[] = { "pxyz","axyz","align","headTo" };\n\t\tint notAllowedLn = sizeof(notAllowed) \/ sizeof(notAllowed[0]);\n\t\tfor (int i = 0; i < notAllowedLn; i++)\n\t\t\tif (varExists(notAllowed[i], pML->currentTag)) {\n\t\t\t\tmylog("ERROR in ModelLoader::processTag: use %s in <\/group>: %s\\n", notAllowed[i].c_str(), pML->currentTag.c_str());\n\t\t\t\treturn -1;\n\t\t\t}\n\t\tpMB->lockGroup(pMB);\n\t\t\/\/mark\n\t\tif (varExists("mark", pML->currentTag))\n\t\t\taddMark(pMB->pCurrentGroup->marks, getStringValue("mark", pML->currentTag));\n\t\treturn 1;\n\t}\n\tif (pML->tagName.compare("\/group") == 0) {\n\t\tGroupTransform gt;\n\t\tfillProps_gt(>, pMB, pML->currentTag);\n\t\tgt.executeGroupTransform(pMB);\n\n\t\tpMB->releaseGroup(pMB);\n\t\treturn 1;\n\t}\n\tif (pML->tagName.compare("a") == 0)\n\t\treturn processTag_a(pML); \/\/apply \n\tif (pML->tagName.compare("clone") == 0)\n\t\treturn processTag_clone(pML);\n\tif (pML->tagName.compare("\/clone") == 0)\n\t\treturn processTag_clone(pML);\n\tif (pML->tagName.compare("do") == 0)\n\t\treturn processTag_do(pML);\n\n\t\/\/mylog("%s, %s \/group?=%d\\n",pML->currentTag.c_str(), pML->tagName.c_str(), (pML->tagName.compare("\/group") == 0));\n\tmylog("ERROR in ModelLoader::processTag, unhandled tag %s, file %s\\n", pML->currentTag.c_str(), pML->fullPath.c_str());\n\treturn -1;\n}\nint ModelLoader::fillProps_vs(VirtualShape* pVS, std::string tagStr) {\n\t\/\/sets virtual shape\n\tsetCharsValue(pVS->shapeType, 20, "vs", tagStr);\n\tsetFloatArray(pVS->whl, 3, "whl", tagStr);\n\t\/\/extensions\n\tfloat ext;\n\tif (varExists("ext", tagStr)) {\n\t\tsetFloatValue(&ext, "ext", tagStr);\n\t\tpVS->setExt(ext);\n\t}\n\tif (varExists("extX", tagStr)) {\n\t\tsetFloatValue(&ext, "extX", tagStr);\n\t\tpVS->setExtX(ext);\n\t}\n\tif (varExists("extY", tagStr)) {\n\t\tsetFloatValue(&ext, "extY", tagStr);\n\t\tpVS->setExtY(ext);\n\t}\n\tif (varExists("extZ", tagStr)) {\n\t\tsetFloatValue(&ext, "extZ", tagStr);\n\t\tpVS->setExtZ(ext);\n\t}\n\tsetFloatValue(&pVS->extU, "extU", tagStr);\n\tsetFloatValue(&pVS->extD, "extD", tagStr);\n\tsetFloatValue(&pVS->extL, "extL", tagStr);\n\tsetFloatValue(&pVS->extR, "extR", tagStr);\n\tsetFloatValue(&pVS->extF, "extF", tagStr);\n\tsetFloatValue(&pVS->extB, "extB", tagStr);\n\t\/\/sections\n\tsetIntValue(&pVS->sectionsR, "sectR", tagStr);\n\tsetIntValue(&pVS->sections[0], "sectX", tagStr);\n\tsetIntValue(&pVS->sections[1], "sectY", tagStr);\n\tsetIntValue(&pVS->sections[2], "sectZ", tagStr);\n\n\t\/\/mylog("pVS->shapeType=%s whl=%fx%fx%f\\n", pVS->shapeType, pVS->whl[0], pVS->whl[1], pVS->whl[2]);\n\treturn 1;\n}\nint ModelLoader::processTag_a(ModelLoader* pML) {\n\t\/\/apply\n\tModelBuilder* pMB = pML->pModelBuilder;\n\tstd::string tagStr = pML->currentTag;\n\tpMB->lockGroup(pMB);\n\t\/\/mark\n\tif (varExists("mark", tagStr))\n\t\taddMark(pMB->pCurrentGroup->marks, getStringValue("mark", tagStr));\n\n\tstd::vector<std::string> applyTosVector = splitString(pML->getStringValue("a", tagStr), ",");\n\tMaterial* pMT = pMB->materialsList.at(pMB->usingMaterialN);\n\tint texN = pMT->uTex1mask;\n\tif (texN < 0)\n\t\ttexN = pMT->uTex0;\n\tfloat xywh[4] = { 0,0,1,1 };\n\tsetFloatArray(xywh, 4, "xywh", tagStr);\n\tstd::string flipStr = getStringValue("flip", tagStr);\n\tTexCoords tc;\n\ttc.set(texN, xywh[0], xywh[1], xywh[2], xywh[3], flipStr);\n\n\tsetFloatArray(xywh, 4, "xywh2nm", tagStr);\n\tflipStr = getStringValue("flip2nm", tagStr);\n\tTexCoords tc2nm;\n\ttc2nm.set(pMT->uTex2nm, xywh[0], xywh[1], xywh[2], xywh[3], flipStr);\n\n\t\/\/adjusted VirtualShape\n\tVirtualShape* pVS_a = new VirtualShape(*pMB->pCurrentVShape);\n\tfillProps_vs(pVS_a, tagStr);\n\n\tfor (int aN = 0; aN < (int)applyTosVector.size(); aN++) {\n\t\t\/\/pMB->buildFace(pMB, applyTosVector.at(aN), pMB->pCurrentVShape, &tc, &tc2nm);\n\t\tpMB->buildFace(pMB, applyTosVector.at(aN), pVS_a, &tc, &tc2nm);\n\t}\n\tdelete pVS_a;\n\t\/\/mylog("vertsN=%d\\n",pMB->vertices.size());\n\n\tGroupTransform GT_a;\n\tfillProps_gt(>_a, pMB, tagStr);\n\tGT_a.executeGroupTransform(pMB);\n\n\tpMB->releaseGroup(pMB);\n\treturn 1;\n}\nint ModelLoader::processTag_clone(ModelLoader* pML) {\n\tModelBuilder* pMB = pML->pModelBuilder;\n\tif (pML->tagName.compare("clone") == 0) {\n\t\t\/\/mark what to clone\n\t\tGroupTransform gt;\n\t\tgt.pGroup = pMB->pLastClosedGroup;\n\t\tgt.flagSelection(>, &pMB->vertices, &pMB->triangles);\n\n\t\t\/\/cloning\n\t\tpMB->lockGroup(pMB);\n\t\tgt.cloneFlagged(pMB, &pMB->vertices, &pMB->triangles, &pMB->vertices, &pMB->triangles);\n\t}\n\tGroupTransform gt;\n\tfillProps_gt(>, pMB, pML->currentTag);\n\tgt.executeGroupTransform(pMB);\n\n\tif (pML->tagName.compare("\/clone") == 0 || pML->closedTag) {\n\t\tpMB->releaseGroup(pMB);\n\t}\n\treturn 1;\n}\nint ModelLoader::addMark(char* marks, std::string newMark) {\n\tif (newMark.empty())\n\t\treturn 0;\n\tstd::string allMarks;\n\tallMarks.assign(marks);\n\tallMarks.append("<"+ newMark+">");\n\tmyStrcpy_s(marks,124, allMarks.c_str());\n\treturn 1;\n}\n\nint ModelLoader::fillProps_gt(GroupTransform* pGT, ModelBuilder* pMB, std::string tagStr) {\n\tpGT->pGroup = pMB->pCurrentGroup;\n\t\/\/position\n\tsetFloatArray(pGT->shift, 3, "pxyz", tagStr);\n\tsetFloatValue(&pGT->shift[0], "px", tagStr);\n\tsetFloatValue(&pGT->shift[1], "py", tagStr);\n\tsetFloatValue(&pGT->shift[2], "pz", tagStr);\n\t\/\/angles\n\tsetFloatArray(pGT->spin, 3, "axyz", tagStr);\n\tsetFloatValue(&pGT->spin[0], "ax", tagStr);\n\tsetFloatValue(&pGT->spin[1], "ay", tagStr);\n\tsetFloatValue(&pGT->spin[2], "az", tagStr);\n\t\/\/scale\n\tsetFloatArray(pGT->scale, 3, "scale", tagStr);\n\n\tpGT->onThe = getStringValue("onThe", tagStr);\n\tpGT->allign = getStringValue("allign", tagStr);\n\tpGT->headZto = getStringValue("headZto", tagStr);\n\t\/\/limit to\n\tif(varExists("all",tagStr))\n\t\tpGT->pGroup = NULL;\n\tif (varExists("lastClosedGroup", tagStr))\n\t\tpGT->pGroup = pMB->pLastClosedGroup;\n\tif (varExists("markedAs", tagStr))\n\t\tpGT->limit2mark(pGT, getStringValue("markedAs", tagStr));\n\tsetFloatArray(pGT->pMin, 3, "xyzMin", tagStr);\n\tsetFloatArray(pGT->pMax, 3, "xyzMax", tagStr);\n\treturn 1;\n}\nint ModelLoader::processTag_do(ModelLoader* pML) {\n\tModelBuilder* pMB = pML->pModelBuilder;\n\tGroupTransform gt;\n\tfillProps_gt(>, pMB, pML->currentTag);\n\tgt.flagSelection(>, &pMB->vertices, &pMB->triangles);\n\tgt.transformFlagged(>, &pMB->vertices);\n\treturn 1;\n}\n\n<\/pre><\/div>\n\n\n
\n\n\n\n
<\/p>\n\n\n\n
\n\n\n\n\n#include "TheGame.h"\n#include "platform.h"\n#include "utils.h"\n#include "linmath.h"\n#include "Texture.h"\n#include "Shader.h"\n#include "DrawJob.h"\n#include "ModelBuilder.h"\n#include "TexCoords.h"\n#include "ModelLoader.h"\n\nextern std::string filesRoot;\nextern float degrees2radians;\n\nstd::vector<GameSubj*> TheGame::gameSubjs;\n\nint TheGame::getReady() {\n bExitGame = false;\n Shader::loadShaders();\n glEnable(GL_CULL_FACE);\n\n glEnable(GL_DEPTH_TEST);\n glDepthFunc(GL_LEQUAL);\n glDepthMask(GL_TRUE);\n\n int subjN = ModelLoader::loadModel(&gameSubjs, "\/dt\/models\/misc\/marlboro01\/root01.txt", "");\n GameSubj* pGS = gameSubjs.at(subjN);\n pGS->name.assign("box1");\n pGS->ownSpeed.setDegrees(0, 2, 0);\n \/\/pGS->ownCoords.setDegrees(0, 90, 0);\n\n \/\/===== set up camera\n mainCamera.ownCoords.setDegrees(15, 180, 0); \/\/set camera angles\/orientation\n mainCamera.viewRangeDg = 30;\n mainCamera.stageSize[0] = 80;\n mainCamera.stageSize[1] = 120;\n memcpy(mainCamera.lookAtPoint, pGS->ownCoords.pos, sizeof(float) * 3);\n mainCamera.onScreenResize();\n\n \/\/===== set up light\n v3set(dirToMainLight, -1, 1, 1);\n vec3_norm(dirToMainLight, dirToMainLight);\n\n return 1;\n}\nint TheGame::drawFrame() {\n myPollEvents();\n\n \/\/glClearColor(0.0, 0.0, 0.5, 1.0);\n glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n \/\/calculate halfVector\n float dirToCamera[4] = { 0,0,-1,0 }; \/\/-z\n mat4x4_mul_vec4plus(dirToCamera, *mainCamera.ownCoords.getRotationMatrix(), dirToCamera, 0);\n\n float uHalfVector[4] = { 0,0,0,0 };\n for (int i = 0; i < 3; i++)\n uHalfVector[i] = (dirToCamera[i] + dirToMainLight[i]) \/ 2;\n vec3_norm(uHalfVector, uHalfVector);\n\n mat4x4 mProjection, mViewProjection, mMVP, mMV4x4;\n \/\/mat4x4_ortho(mProjection, -(float)screenSize[0] \/ 2, (float)screenSize[0] \/ 2, -(float)screenSize[1] \/ 2, (float)screenSize[1] \/ 2, 100.f, 500.f);\n float nearClip = mainCamera.focusDistance - 50;\n float farClip = mainCamera.focusDistance + 50;\n if (nearClip < 0) nearClip = 0;\n mat4x4_perspective(mProjection, mainCamera.viewRangeDg * degrees2radians, screenAspectRatio, nearClip, farClip);\n mat4x4_mul(mViewProjection, mProjection, mainCamera.lookAtMatrix);\n mViewProjection[1][3] = 0; \/\/keystone effect\n\n \/\/scan subjects\n int subjsN = gameSubjs.size();\n for (int subjN = 0; subjN < subjsN; subjN++) {\n GameSubj* pGS = gameSubjs.at(subjN);\n \/\/behavior - apply rotation speed\n pGS->moveSubj();\n \/\/prepare subject for rendering\n pGS->buildModelMatrix(pGS);\n \/\/build MVP matrix for given subject\n mat4x4_mul(mMVP, mViewProjection, pGS->ownModelMatrix);\n \/\/build Model-View (rotation) matrix for normals\n mat4x4_mul(mMV4x4, mainCamera.lookAtMatrix, (vec4*)pGS->ownCoords.getRotationMatrix());\n \/\/convert to 3x3 matrix\n float mMV3x3[3][3];\n for (int y = 0; y < 3; y++)\n for (int x = 0; x < 3; x++)\n mMV3x3[y][x] = mMV4x4[y][x];\n \/\/render subject\n for (int i = 0; i < pGS->djTotalN; i++) {\n DrawJob* pDJ = DrawJob::drawJobs.at(pGS->djStartN + i);\n pDJ->execute((float*)mMVP, *mMV3x3, dirToMainLight, uHalfVector, NULL);\n }\n }\n \/\/synchronization\n while (1) {\n long long int currentMillis = getSystemMillis();\n long long int millisSinceLastFrame = currentMillis - lastFrameMillis;\n if (millisSinceLastFrame >= millisPerFrame) {\n lastFrameMillis = currentMillis;\n break;\n }\n }\n mySwapBuffers();\n return 1;\n}\n\nint TheGame::cleanUp() {\n int itemsN = gameSubjs.size();\n \/\/delete all UISubjs\n for (int i = 0; i < itemsN; i++) {\n GameSubj* pGS = gameSubjs.at(i);\n delete pGS;\n }\n gameSubjs.clear();\n \/\/clear all other classes\n Texture::cleanUp();\n Shader::cleanUp();\n DrawJob::cleanUp();\n return 1;\n}\nint TheGame::onScreenResize(int width, int height) {\n if (screenSize[0] == width && screenSize[1] == height)\n return 0;\n screenSize[0] = width;\n screenSize[1] = height;\n screenAspectRatio = (float)width \/ height;\n glViewport(0, 0, width, height);\n mainCamera.onScreenResize();\n mylog(" screen size %d x %d\\n", width, height);\n return 1;\n}\nint TheGame::run() {\n getReady();\n while (!bExitGame) {\n drawFrame();\n }\n cleanUp();\n return 1;\n}\nGameSubj* TheGame::newGameSubj(std::string subjClass) {\n return (new GameSubj());\n}\n\n<\/pre><\/div>\n\n\n
\n\n\n\n
<\/p>\n\n\n\n
\n\n\n\nAndroid<\/h2>\n\n\n\n
\n\n\n\n\n#include "platform.h"\n#include "TheGame.h"\n\n#include <string>\n#include <vector>\n\n#include <sys\/stat.h>\t\/\/mkdir for Android\n\nstd::string filesRoot;\n\nTheGame theGame;\n\nstruct android_app* androidApp;\n\nASensorManager* sensorManager;\nconst ASensor* accelerometerSensor;\nASensorEventQueue* sensorEventQueue;\n\nEGLDisplay androidDisplay;\nEGLSurface androidSurface;\nEGLContext androidContext;\n\n\/**\n* Initialize an EGL context for the current display.\n*\/\nstatic int engine_init_display(struct engine* engine) {\n\t\/\/ initialize OpenGL ES and EGL\n\n\t\/*\n\t* Here specify the attributes of the desired configuration.\n\t* Below, we select an EGLConfig with at least 8 bits per color\n\t* component compatible with on-screen windows\n\t*\/\n\tconst EGLint attribs[] = {\n\t\tEGL_SURFACE_TYPE, EGL_WINDOW_BIT,\n\t\tEGL_BLUE_SIZE, 8,\n\t\tEGL_GREEN_SIZE, 8,\n\t\tEGL_RED_SIZE, 8,\n\t\tEGL_DEPTH_SIZE, 16,\n\t\tEGL_NONE\n\t};\n\tEGLint format;\n\tEGLint numConfigs;\n\tEGLConfig config;\n\tEGLSurface surface;\n\tEGLContext context;\n\n\tEGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);\n\n\teglInitialize(display, 0, 0);\n\n\t\/* Here, the application chooses the configuration it desires. In this\n\t* sample, we have a very simplified selection process, where we pick\n\t* the first EGLConfig that matches our criteria *\/\n\teglChooseConfig(display, attribs, &config, 1, &numConfigs);\n\n\t\/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is\n\t* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().\n\t* As soon as we picked a EGLConfig, we can safely reconfigure the\n\t* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. *\/\n\teglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);\n\n\tANativeWindow_setBuffersGeometry(androidApp->window, 0, 0, format);\n\n\tsurface = eglCreateWindowSurface(display, config, androidApp->window, NULL);\n\n\tEGLint contextAttribs[] =\n\t{\n\t\tEGL_CONTEXT_CLIENT_VERSION, 3,\n\t\tEGL_NONE\n\t};\n\tcontext = eglCreateContext(display, config, NULL, contextAttribs);\n\n\n\tif (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {\n\t\tmylog("ERROR: Unable to eglMakeCurrent");\n\t\treturn -1;\n\t}\n\n\tandroidDisplay = display;\n\tandroidContext = context;\n\tandroidSurface = surface;\n\n\treturn 0;\n}\n\n\/**\n* Tear down the EGL context currently associated with the display.\n*\/\nstatic void engine_term_display() {\n\n\tif (androidDisplay != EGL_NO_DISPLAY) {\n\t\teglMakeCurrent(androidDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);\n\t\tif (androidContext != EGL_NO_CONTEXT) {\n\t\t\teglDestroyContext(androidDisplay, androidContext);\n\t\t}\n\t\tif (androidSurface != EGL_NO_SURFACE) {\n\t\t\teglDestroySurface(androidDisplay, androidSurface);\n\t\t}\n\t\teglTerminate(androidDisplay);\n\t}\n\tandroidDisplay = EGL_NO_DISPLAY;\n\tandroidContext = EGL_NO_CONTEXT;\n\tandroidSurface = EGL_NO_SURFACE;\n}\n\n\/**\n* Process the next input event.\n*\/\nstatic int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {\n\tif (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {\n\t\t\/\/engine->state.x = AMotionEvent_getX(event, 0);\n\t\t\/\/engine->state.y = AMotionEvent_getY(event, 0);\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\n\/**\n* Process the next main command.\n*\/\nstatic void engine_handle_cmd(struct android_app* app, int32_t cmd) {\n\tstruct engine* engine = (struct engine*)app->userData;\n\tswitch (cmd) {\n\tcase APP_CMD_INIT_WINDOW:\n\t\t\/\/ The window is being shown, get it ready.\n\t\tif (androidApp->window != NULL) {\n\t\t\tengine_init_display(engine);\n\t\t\t\/\/engine_draw_frame(engine);\n\t\t}\n\t\tbreak;\n\tcase APP_CMD_TERM_WINDOW:\n\t\t\/\/ The window is being hidden or closed, clean it up.\n\t\tengine_term_display();\n\t\tbreak;\n\tcase APP_CMD_GAINED_FOCUS:\n\t\t\/\/ When our app gains focus, we start monitoring the accelerometer.\n\t\tif (accelerometerSensor != NULL) {\n\t\t\tASensorEventQueue_enableSensor(sensorEventQueue,\n\t\t\t\taccelerometerSensor);\n\t\t\t\/\/ We'd like to get 60 events per second (in microseconds).\n\t\t\tASensorEventQueue_setEventRate(sensorEventQueue,\n\t\t\t\taccelerometerSensor, (1000L \/ 60) * 1000);\n\t\t}\n\t\tbreak;\n\tcase APP_CMD_LOST_FOCUS:\n\t\t\/\/ When our app loses focus, we stop monitoring the accelerometer.\n\t\t\/\/ This is to avoid consuming battery while not being used.\n\t\tif (accelerometerSensor != NULL) {\n\t\t\tASensorEventQueue_disableSensor(sensorEventQueue,\n\t\t\t\taccelerometerSensor);\n\t\t}\n\t\t\/\/ Also stop animating.\n\t\t\/\/engine_draw_frame(engine);\n\t\tbreak;\n\t}\n}\nstatic std::vector<std::string> list_assets(android_app* app, const char* asset_path)\n{ \/\/by Marcel Smit, stolen from https:\/\/github.com\/android\/ndk-samples\/issues\/603\n\tstd::vector<std::string> result;\n\n\tJNIEnv* env = nullptr;\n\tapp->activity->vm->AttachCurrentThread(&env, nullptr);\n\n\tauto context_object = app->activity->clazz;\n\tauto getAssets_method = env->GetMethodID(env->GetObjectClass(context_object), "getAssets", "()Landroid\/content\/res\/AssetManager;");\n\tauto assetManager_object = env->CallObjectMethod(context_object, getAssets_method);\n\tauto list_method = env->GetMethodID(env->GetObjectClass(assetManager_object), "list", "(Ljava\/lang\/String;)[Ljava\/lang\/String;");\n\n\tjstring path_object = env->NewStringUTF(asset_path);\n\tauto files_object = (jobjectArray)env->CallObjectMethod(assetManager_object, list_method, path_object);\n\tenv->DeleteLocalRef(path_object);\n\tauto length = env->GetArrayLength(files_object);\n\n\tfor (int i = 0; i < length; i++)\n\t{\n\t\tjstring jstr = (jstring)env->GetObjectArrayElement(files_object, i);\n\t\tconst char* filename = env->GetStringUTFChars(jstr, nullptr);\n\t\tif (filename != nullptr)\n\t\t{\n\t\t\tresult.push_back(filename);\n\t\t\tenv->ReleaseStringUTFChars(jstr, filename);\n\t\t}\n\t\tenv->DeleteLocalRef(jstr);\n\t}\n\tapp->activity->vm->DetachCurrentThread();\n\treturn result;\n}\n\nint updateAssets() {\n\t\/\/get APK apkLastUpdateTime timestamp\n\tJNIEnv* env = nullptr;\n\tandroidApp->activity->vm->AttachCurrentThread(&env, nullptr);\n\tjobject context_object = androidApp->activity->clazz;\n\tjmethodID getPackageNameMid_method = env->GetMethodID(env->GetObjectClass(context_object), "getPackageName", "()Ljava\/lang\/String;");\n\tjstring packageName = (jstring)env->CallObjectMethod(context_object, getPackageNameMid_method);\n\tjmethodID getPackageManager_method = env->GetMethodID(env->GetObjectClass(context_object), "getPackageManager", "()Landroid\/content\/pm\/PackageManager;");\n\tjobject packageManager_object = env->CallObjectMethod(context_object, getPackageManager_method);\n\tjmethodID getPackageInfo_method = env->GetMethodID(env->GetObjectClass(packageManager_object), "getPackageInfo", "(Ljava\/lang\/String;I)Landroid\/content\/pm\/PackageInfo;");\n\tjobject packageInfo_object = env->CallObjectMethod(packageManager_object, getPackageInfo_method, packageName, 0x0);\n\tjfieldID updateTimeFid = env->GetFieldID(env->GetObjectClass(packageInfo_object), "lastUpdateTime", "J");\n\tlong int apkLastUpdateTime = env->GetLongField(packageInfo_object, updateTimeFid);\n\t\/\/ APK updateTime timestamp retrieved\n\t\/\/ compare with saved timestamp\n\tstd::string updateTimeFilePath = filesRoot + "\/dt\/apk_update_time.bin";\n\tFILE* inFile = fopen(updateTimeFilePath.c_str(), "r");\n\tif (inFile != NULL)\n\t{\n\t\tlong int savedUpdateTime;\n\t\tfread(&savedUpdateTime, 1, sizeof(savedUpdateTime), inFile);\n\t\tfclose(inFile);\n\t\tif (savedUpdateTime == apkLastUpdateTime) {\n\t\t\tmylog("Assets are up to date.\\n");\n\t\t\treturn 0;\n\t\t}\n\t}\n\t\/\/ if here - need to update assets\n\tAAssetManager* am = androidApp->activity->assetManager;\n\tint buffSize = 1000000; \/\/guess, should be enough?\n\tchar* buff = new char[buffSize];\n\n\tstd::vector<std::string> dirsToCheck; \/\/list of assets folders to check\n\tdirsToCheck.push_back("dt"); \/\/root folder\n\twhile (dirsToCheck.size() > 0) {\n\t\t\/\/open last element from directories vector\n\t\tstd::string dirPath = dirsToCheck.back();\n\t\tdirsToCheck.pop_back(); \/\/delete last element\n\t\t\/\/mylog("Scanning directory <%s>\\n", dirPath.c_str());\n\t\t\/\/make sure folder exists on local drive\n\t\tstd::string outPath = filesRoot + "\/" + dirPath; \/\/ .c_str();\n\t\tstruct stat info;\n\t\tint statRC = stat(outPath.c_str(), &info);\n\t\tif (statRC == 0)\n\t\t\tmylog("%s folder exists.\\n", outPath.c_str());\n\t\telse {\n\t\t\t\/\/ mylog("Try to create %s\\n", outPath.c_str());\n\t\t\tint status = mkdir(outPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);\n\t\t\tif (status == 0)\n\t\t\t\tmylog("%s folder added.\\n", outPath.c_str());\n\t\t\telse {\n\t\t\t\tmylog("ERROR creating, status=%d, errno: %s.\\n", status, std::strerror(errno));\n\t\t\t}\n\t\t}\n\t\t\/\/get folder's content\n\t\tstd::vector<std::string> dirItems = list_assets(androidApp, dirPath.c_str());\n\t\tint itemsN = dirItems.size();\n\t\t\/\/scan directory items\n\t\tfor (int i = 0; i < itemsN; i++) {\n\t\t\tstd::string itemPath = dirPath + "\/" + dirItems.at(i).c_str();\n\t\t\t\/\/mylog("New item: <%s> - ", itemPath.c_str());\n\t\t\t\/\/try to open it to see if it's a file\n\t\t\tAAsset* asset = AAssetManager_open(am, itemPath.c_str(), AASSET_MODE_UNKNOWN);\n\t\t\tif (asset != NULL) {\n\t\t\t\tlong size = AAsset_getLength(asset);\n\t\t\t\t\/\/mylog("It's a file, size = %d - ", size);\n\t\t\t\tif (size > buffSize) {\n\t\t\t\t\tmylog("ERROR in main.cpp->updateAssets(): File %s is too big, skipped.\\n", itemPath.c_str());\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tAAsset_read(asset, buff, size);\n\t\t\t\t\toutPath = filesRoot + "\/" + itemPath;\n\t\t\t\t\tFILE* outFile = fopen(outPath.c_str(), "w+");\n\t\t\t\t\tif (outFile != NULL)\n\t\t\t\t\t{\n\t\t\t\t\t\tfwrite(buff, 1, size, outFile);\n\t\t\t\t\t\tfflush(outFile);\n\t\t\t\t\t\tfclose(outFile);\n\t\t\t\t\t\tmylog("%s saved\\n", outPath.c_str());\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tmylog("ERROR in main.cpp->updateAssets(): Can't create file %s\\n", itemPath.c_str());\n\t\t\t\t}\n\t\t\t\tAAsset_close(asset);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdirsToCheck.push_back(itemPath);\n\t\t\t\t\/\/mylog("It's a folder, add to folders list to check.\\n");\n\t\t\t}\n\t\t}\n\t\tdirItems.clear();\n\t}\n\tdelete[] buff;\n\t\/\/ save updateTime\n\tFILE* outFile = fopen(updateTimeFilePath.c_str(), "w+");\n\tif (outFile != NULL)\n\t{\n\t\tfwrite(&apkLastUpdateTime, 1, sizeof(apkLastUpdateTime), outFile);\n\t\tfflush(outFile);\n\t\tfclose(outFile);\n\t}\n\telse\n\t\tmylog("ERROR creating %s\\n", updateTimeFilePath.c_str());\n\treturn 1;\n}\n\/**\n* This is the main entry point of a native application that is using\n* android_native_app_glue. It runs in its own thread, with its own\n* event loop for receiving input events and doing other things.\n*\/\nvoid android_main(struct android_app* state) {\n\n\t\/\/state->userData = &engine;\n\tstate->onAppCmd = engine_handle_cmd;\n\tstate->onInputEvent = engine_handle_input;\n\tandroidApp = state;\n\n\t\/\/ Prepare to monitor accelerometer\n\tsensorManager = ASensorManager_getInstance();\n\taccelerometerSensor = ASensorManager_getDefaultSensor(sensorManager,\n\t\tASENSOR_TYPE_ACCELEROMETER);\n\tsensorEventQueue = ASensorManager_createEventQueue(sensorManager,\n\t\tstate->looper, LOOPER_ID_USER, NULL, NULL);\n\n\t\/\/ Read all pending events.\n\tint ident;\n\tint events;\n\tstruct android_poll_source* source;\n\t\/\/wait for display\n\twhile (androidDisplay == NULL) {\n\t\t\/\/ No display yet.\n\t\t\/\/std::this_thread::sleep_for(std::chrono::seconds(1));\n\t\t\/\/mylog("No display yet\\n");\n\t\t\/\/wait for event\n\t\twhile ((ident = ALooper_pollAll(0, NULL, &events,\n\t\t\t(void**)&source)) >= 0) {\n\t\t\t\/\/ Process this event.\n\t\t\tif (source != NULL) {\n\t\t\t\tsource->process(state, source);\n\t\t\t}\n\t\t}\n\t}\n\n\tEGLint w, h;\n\teglQuerySurface(androidDisplay, androidSurface, EGL_WIDTH, &w);\n\teglQuerySurface(androidDisplay, androidSurface, EGL_HEIGHT, &h);\n\ttheGame.onScreenResize(w, h);\n\n\t\/\/retrieving files root\n\tfilesRoot.assign(androidApp->activity->internalDataPath);\n\tmylog("filesRoot = %s\\n", filesRoot.c_str());\n\n\tupdateAssets();\n\n\ttheGame.run();\n\n\tengine_term_display();\n}\n\n<\/pre><\/div>\n\n\n
\n\n\n\n
\n\n\n\n