Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the 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

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902

Warning: Cannot modify header information - headers already sent by (output started at /home/ruwritingagame/public_html/wp-includes/functions.php:6131) in /home/ruwritingagame/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1902
{"id":697,"date":"2021-12-08T01:12:29","date_gmt":"2021-12-08T01:12:29","guid":{"rendered":"https:\/\/writingagame.com\/?p=697"},"modified":"2022-01-26T20:51:22","modified_gmt":"2022-01-26T20:51:22","slug":"chapter-22-screen-resize","status":"publish","type":"post","link":"https:\/\/writingagame.ru\/index.php\/2021\/12\/08\/chapter-22-screen-resize\/","title":{"rendered":"\u0413\u043b\u0430\u0432\u0430 22. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 \u044d\u043a\u0440\u0430\u043d\u0430"},"content":{"rendered":"\n

\u041f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 \u044d\u043a\u0440\u0430\u043d\u0430 \u043d\u0430\u0434\u043e \u043f\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0443 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0441\u0446\u0435\u043d\u0430 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043b\u0430 \u043d\u043e\u0432\u044b\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0446\u0435\u043d\u044b, \u0441\u043a\u0430\u0436\u0435\u043c, 500×300 (\u0447\u0442\u043e\u0431\u044b \u043a\u0443\u0431\u0438\u043a \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0441\u044f \u0432 \u044d\u043a\u0440\u0430\u043d). \u0423\u0433\u043e\u043b \u0437\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u0443 \u043d\u0430\u0441 30 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432.<\/p>\n\n\n\n

<\/p>\n\n\n\n

<\/p>\n\n\n\n

\u0437\u043d\u0430\u0447\u0438\u0442, ?<\/strong> \/ 250 = \u043a\u043e\u0441\u0438\u043d\u0443\u0441(15) \/ \u0441\u0438\u043d\u0443\u0441(15) = \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15)<\/em><\/p>\n\n\n\n

?<\/strong> = 250 * \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15) = 250 * 3.73 = 923<\/em><\/p>\n\n\n\n

\u0447\u0442\u043e \u043d\u0435\u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043d\u0430\u0448\u0435\u0439 1000 (\u0441\u0442\u0440\u043e\u043a\u0430 69 \u0432 TheGame.cpp<\/em>) \u0438 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442 \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u0432 \u044d\u043a\u0440\u0430\u043d \u0410\u043d\u0434\u0440\u043e\u0438\u0434\u0430.<\/p>\n\n\n\n

\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u044b \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u0430, \u0430 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445:<\/p>\n\n\n\n

\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c VS, \u043e\u0442\u043a\u0440\u043e\u0435\u043c C:\\CPP\\a997modeler<\/em>\\p_windows\\p_windows.sln<\/em>, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 (\u0437\u0435\u043b\u0435\u043d\u0430\u044f \u0441\u0442\u0440\u0435\u043b\u043a\u0430), \u043f\u043e\u0438\u0433\u0440\u0430\u0435\u043c \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c\u0438 \u043e\u043a\u043d\u0430 (\u043e\u0442 \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u0443\u0437\u043a\u043e\u0433\u043e \u043a \u043d\u0438\u0437\u043a\u043e\u043c\u0443 \u0448\u0438\u0440\u043e\u043a\u043e\u043c\u0443). \u0412\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 (\u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u043e \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e\u0441\u0442\u044c\u044e) \u0447\u0442\u043e \u043d\u0430\u0448\u0430 1000 (\u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b) \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e <\/strong>\u043f\u043e \u0412\u0415\u0420\u0422\u0418\u041a\u0410\u041b\u0418, \u043d\u0435 \u043f\u043e \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u0430\u043c \u043d\u0435 \u043d\u0430\u0434\u043e \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c 500 \u0435\u0434\u0438\u043d\u0438\u0446 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e, \u043f\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e 300, \u0437\u043d\u0430\u0447\u0438\u0442<\/p>\n\n\n\n

cameraDistanceV (\u0434\u043b\u044f \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438) = 150 * \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15)<\/em><\/p>\n\n\n\n

\u0414\u043b\u044f \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 \u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0443\u0447\u0435\u0441\u0442\u044c screen aspect ratio<\/em>, \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0448\u0438\u0440\u0438\u043d\u044b \u044d\u043a\u0440\u0430\u043d\u0430 \u043a \u0432\u044b\u0441\u043e\u0442\u0435, \u0437\u043d\u0430\u0447\u0438\u0442<\/p>\n\n\n\n

cameraDistanceH (\u0434\u043b\u044f \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438) = 250 * \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15) \/ screenAspectRatio<\/em><\/p>\n\n\n\n

\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430 \u043c\u043e\u0435\u043c S20 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435 \u0440\u0430\u0437\u043c\u0435\u0440 \u044d\u043a\u0440\u0430\u043d\u0430 1080 X 2400, \u0437\u043d\u0430\u0447\u0438\u0442<\/p>\n\n\n\n

screenAspectRatio = 1080 \/ 2400 = 0.45<\/em><\/p>\n\n\n\n

\u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15) = 3.73<\/em>, \u0437\u043d\u0430\u0447\u0438\u0442:<\/p>\n\n\n\n

cameraDistanceV = 150 * \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441<\/em>(15) = 150 * 3.73 = 560<\/em><\/p>\n\n\n\n

cameraDistanceH = 250 * \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441<\/em>(15) \/ screenAspectRatio = 250 * 3.73 \/ 0.45 = 2072<\/em><\/p>\n\n\n\n

\u0414\u043b\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0431\u041e\u043b\u044c\u0448\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, 2072<\/strong>, \u0447\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0440\u0430\u0437\u0443\u043c\u043d\u043e. \u0421 \u0422\u0410\u041a\u041e\u0413\u041e \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u044f – \u0442\u043e\u0447\u043d\u043e \u0432\u043f\u0438\u0448\u0435\u0442\u0441\u044f.<\/p>\n\n\n\n

\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e, \u0440\u0430\u0437\u043c\u0435\u0440 \u044d\u043a\u0440\u0430\u043d\u0430 \u0441\u0442\u0430\u043d\u0435\u0442 2400 X 1080. \u0437\u043d\u0430\u0447\u0438\u0442<\/p>\n\n\n\n

screenAspectRatio = 2400 \/ 1080 = 2.22<\/em>, \u0437\u043d\u0430\u0447\u0438\u0442:<\/p>\n\n\n\n

cameraDistanceV<\/strong> <\/em>\u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0442\u043e\u0439 \u0436\u0435, 560<\/em>, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f<\/p>\n\n\n\n

cameraDistanceH = 250 * \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15) \/ screenAspectRatio = 250 * 3.73 \/ 2.22 = 420<\/em>, \u0442\u0430\u043a \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u041e\u043b\u044c\u0448\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435, 560<\/strong>, \u0447\u0442\u043e \u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438<\/strong>.<\/p>\n\n\n\n

\u0412\u043e\u0442 \u0422\u0415\u041f\u0415\u0420\u042c \u0443 \u043d\u0430\u0441 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u043c\u0435\u0440\u044b.<\/p>\n\n\n\n


\n\n\n\n

\u0418\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/strong>:<\/p>\n\n\n\n

1. \u041d\u0443\u0436\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f screenAspectRatio<\/em>.<\/p>\n\n\n\n

\u0417\u0430\u043c\u0435\u043d\u0438\u043c TheGame.h<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n

\n#pragma once\n#include <vector>\n#include "GameSubj.h"\n#include "Camera.h"\n\nclass TheGame\n{\npublic:\n\tint screenSize[2];\n\tfloat screenAspectRatio = 1;\n\tbool bExitGame;\n\tCamera mainCamera;\n\tfloat dirToMainLight[4] = { 1,1,1,0 };\n\n\t\/\/static arrays (vectors) of active GameSubjs\n\tstatic std::vector<GameSubj*> gameSubjs;\npublic:\n\tint run();\n\tint getReady();\n\tint drawFrame();\n\tint cleanUp();\n\tint onScreenResize(int width, int height);\n};\n\n<\/pre><\/div>\n\n\n

<\/p>\n\n\n\n


\n\n\n\n

\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445TheGame::getReady(), TheGame::drawFrame()<\/em> \u0438 \u0432 TheGame::onScreenResize()<\/em> \u0443 \u043d\u0430\u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u0430\u043c\u0435\u0440\u044b. \u0421\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u044d\u0442\u0438\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043b\u0443\u0447\u0448\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0438\u0437 TheGame <\/em>\u0432 \u043a\u043b\u0430\u0441\u0441 Camera<\/em>.<\/p>\n\n\n\n

2. \u0417\u0430\u043c\u0435\u043d\u0438\u043c TheGame.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\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\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    \/\/=== create box ========================\n    GameSubj* pGS = new GameSubj();\n    gameSubjs.push_back(pGS);\n\n    pGS->name.assign("box1");\n    pGS->ownCoords.setPosition(0, 0, 0);\n    pGS->ownCoords.setDegrees(0, 0, 0);\n    pGS->ownSpeed.setDegrees(0,1,0);\n\n    ModelBuilder* pMB = new ModelBuilder();\n    pMB->useSubjN(gameSubjs.size() - 1);\n\n    \/\/define VirtualShape\n    VirtualShape vs;\n    vs.setShapeType("box-tank");\n    vs.whl[0] = 60;\n    vs.whl[1] = 160;\n    vs.whl[2] = 390;\n    vs.setExt(20);\n    vs.extD = 0;\n    vs.extF = 0; \/\/to make front face "flat"\n    vs.sectionsR = 2;\n\n    Material mt;\n    \/\/define material - flat red\n    mt.shaderN = Shader::spN_phong_ucolor;\n    mt.primitiveType = GL_TRIANGLES;\n    mt.uColor.setRGBA(255, 0, 0,255); \/\/red\n    pMB->useMaterial(&mt);\n\n    pMB->buildBoxFace(pMB,"front v", &vs);\n    pMB->buildBoxFace(pMB, "back v", &vs);\n    pMB->buildBoxFace(pMB, "top", &vs);\n    pMB->buildBoxFace(pMB, "bottom", &vs);\n    pMB->buildBoxFace(pMB, "left all", &vs);\n\n    mt.uColor.clear(); \/\/ set to zero;\n    mt.uTex0 = Texture::loadTexture(filesRoot + "\/dt\/sample_img.png");\n    mt.shaderN = Shader::spN_flat_tex;\n    pMB->useMaterial(&mt);\n    TexCoords tc;\n    tc.set(mt.uTex0, 11, 12, 256, 128, "180");\n    pMB->buildBoxFace(pMB, "right all", &vs, &tc);\n\n    pMB->buildDrawJobs(gameSubjs);\n\n    delete pMB;\n\n    \/\/===== set up camera\n    mainCamera.ownCoords.setDegrees(15, 180, 0); \/\/set camera angles\/orientation\n    mainCamera.viewRangeDg = 30;\n    mainCamera.stageSize[0] = 500;\n    mainCamera.stageSize[1] = 375;\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);\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 - 250;\n    float farClip = mainCamera.focusDistance + 250;\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    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}\n\n<\/pre><\/div>\n\n\n

<\/p>\n\n\n\n


\n\n\n\n

3. \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 Camera <\/em> – \u043d\u043e\u0432\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b.<\/p>\n\n\n\n

\u0417\u0430\u043c\u0435\u043d\u0438\u043c Camera.h<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n

\n#pragma once\n#include "Coords.h"\n#include "linmath.h"\n\nclass Camera\n{\npublic:\n\tCoords ownCoords;\n\tmat4x4 lookAtMatrix;\n\tfloat lookAtPoint[3] = { 0,0,0 };\n\tfloat focusDistance = 100;\n\tfloat viewRangeDg = 30;\n\tfloat stageSize[2] = { 500, 375 };\npublic:\n\tfloat pickDistance() { return pickDistance(this); };\n\tstatic float pickDistance(Camera* pCam);\n\tvoid setCameraPosition() { setCameraPosition(this); };\n\tstatic void setCameraPosition(Camera* pCam);\n\tvoid buildLookAtMatrix() { buildLookAtMatrix(this); };\n\tstatic void buildLookAtMatrix(Camera* pCam);\n\tvoid onScreenResize() { onScreenResize(this); };\n\tstatic void onScreenResize(Camera* pCam);\n};\n\n<\/pre><\/div>\n\n\n

<\/p>\n\n\n\n


\n\n\n\n

4. \u041f\u043e\u0434 xEngine <\/em>\u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 C++ file Camera.cpp<\/strong><\/p>\n\n\n\n

Location: C:\\CPP\\engine\\<\/em><\/p>\n\n\n\n

\u041a\u043e\u0434:<\/p>\n\n\n

\n#include "Camera.h"\n#include "TheGame.h"\n#include "utils.h"\n\nextern TheGame theGame;\nextern float degrees2radians;\n\nfloat Camera::pickDistance(Camera* pCam) {\n\tfloat cotangentA = 1.0f \/ tanf(degrees2radians * pCam->viewRangeDg \/ 2);\n\tfloat cameraDistanceV = pCam->stageSize[1] \/ 2 * cotangentA;\n\tfloat cameraDistanceH = pCam->stageSize[0] \/ 2 * cotangentA \/ theGame.screenAspectRatio;\n\tpCam->focusDistance = fmax(cameraDistanceV, cameraDistanceH);\n\treturn pCam->focusDistance;\n}\nvoid Camera::setCameraPosition(Camera* pCam) {\n\tv3set(pCam->ownCoords.pos, 0, 0, -pCam->focusDistance);\n\tmat4x4_mul_vec4plus(pCam->ownCoords.pos, *pCam->ownCoords.getRotationMatrix(), pCam->ownCoords.pos, 1);\n\tfor (int i = 0; i < 3; i++)\n\t\tpCam->ownCoords.pos[i] += pCam->lookAtPoint[i];\n}\nvoid Camera::buildLookAtMatrix(Camera* pCam) {\n\tfloat cameraUp[4] = { 0,1,0,0 }; \/\/y - up\n\tmat4x4_mul_vec4plus(cameraUp, *pCam->ownCoords.getRotationMatrix(), cameraUp, 0);\n\tmat4x4_look_at(pCam->lookAtMatrix, pCam->ownCoords.pos, pCam->lookAtPoint, cameraUp);\n}\nvoid Camera::onScreenResize(Camera* pCam) {\n\tpCam->pickDistance();\n\tpCam->setCameraPosition();\n\tpCam->buildLookAtMatrix();\n}\n\n<\/pre><\/div>\n\n\n

<\/p>\n\n\n\n


\n\n\n\n

5. \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a.<\/p>\n\n\n\n

\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043f\u043b\u043e\u0445\u043e.<\/p>\n\n\n\n


\n\n\n\n

Android<\/h2>\n\n\n\n

6. \u041f\u0435\u0440\u0435-\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c VS. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c C:\\CPP\\a997modeler\\p_android\\p_android.sln<\/em>. <\/p>\n\n\n\n


\n\n\n\n

7. \u041f\u043e\u0434 xEngine <\/em>\u0434\u043e\u0431\u0430\u0432\u0438\u043c existing item Camera.cpp<\/em> \u0438\u0437 C:\\CPP\\engine<\/em><\/p>\n\n\n\n


\n\n\n\n

\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u044e \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 \u044d\u043a\u0440\u0430\u043d\u0430 \u0432 myglPollEvents()<\/em>.<\/p>\n\n\n\n

8. \u0417\u0430\u043c\u0435\u043d\u0438\u043c myplatform.cpp<\/em> \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n

\n#include <android\/log.h>\n#include "stdio.h"\n#include "TheGame.h"\n#include <sys\/stat.h>\t\/\/mkdir for Android\n\nextern struct android_app* androidApp;\nextern const ASensor* accelerometerSensor;\nextern ASensorEventQueue* sensorEventQueue;\n\nextern EGLDisplay androidDisplay;\nextern EGLSurface androidSurface;\nextern TheGame theGame;\n\nvoid mylog(const char* _Format, ...) {\n#ifdef _DEBUG\n    char outStr[1024];\n    va_list _ArgList;\n    va_start(_ArgList, _Format);\n    vsprintf(outStr, _Format, _ArgList);\n    __android_log_print(ANDROID_LOG_INFO, "mylog", outStr, NULL);\n    va_end(_ArgList);\n#endif\n};\n\nvoid mySwapBuffers() {\n\teglSwapBuffers(androidDisplay, androidSurface);\n}\nvoid myPollEvents() {\n\t\/\/ Read all pending events.\n\tint ident;\n\tint events;\n\tstruct android_poll_source* source;\n\n\t\/\/ If not animating, we will block forever waiting for events.\n\t\/\/ If animating, we loop until all events are read, then continue\n\t\/\/ to draw the next frame of animation.\n\twhile ((ident = ALooper_pollAll(0, NULL, &events,\n\t\t(void**)&source)) >= 0) {\n\n\t\t\/\/ Process this event.\n\t\tif (source != NULL) {\n\t\t\tsource->process(androidApp, source);\n\t\t}\n\n\t\t\/\/ If a sensor has data, process it now.\n\t\tif (ident == LOOPER_ID_USER) {\n\t\t\tif (accelerometerSensor != NULL) {\n\t\t\t\tASensorEvent event;\n\t\t\t\twhile (ASensorEventQueue_getEvents(sensorEventQueue,\n\t\t\t\t\t&event, 1) > 0) {\n\t\t\t\t\t\/\/LOGI("accelerometer: x=%f y=%f z=%f",\n\t\t\t\t\t\/\/\tevent.acceleration.x, event.acceleration.y,\n\t\t\t\t\t\/\/\tevent.acceleration.z);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t\/\/ Check if we are exiting.\n\t\tif (androidApp->destroyRequested != 0) {\n\t\t\ttheGame.bExitGame = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\/\/check screen size\n\tEGLint w, h;\n\teglQuerySurface(androidDisplay, androidSurface, EGL_WIDTH, &w);\n\teglQuerySurface(androidDisplay, androidSurface, EGL_HEIGHT, &h);\n\ttheGame.onScreenResize(w, h);\n}\nint myFopen_s(FILE** pFile, const char* filePath, const char* mode) {\n\t*pFile = fopen(filePath, mode);\n\tif (*pFile == NULL) {\n\t\tmylog("ERROR: can't open file %s\\n", filePath);\n\t\treturn -1;\n\t}\n\treturn 1;\n}\nint myMkDir(const char* outPath) {\n\tstruct stat info;\n\tif (stat(outPath, &info) == 0)\n\t\treturn 0; \/\/exists already\n\tint status = mkdir(outPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);\n\tif (status == 0)\n\t\treturn 1; \/\/Successfully created\n\tmylog("ERROR creating, status=%d, errno: %s.\\n", status, std::strerror(errno));\n\treturn -1;\n}\nvoid myStrcpy_s(char* dst, int maxSize, const char* src) {\n\tstrcpy(dst, src);\n\t\/\/fill tail by zeros\n\tint strLen = strlen(dst);\n\tif (strLen < maxSize)\n\t\tfor (int i = strLen; i < maxSize; i++)\n\t\t\tdst[i] = 0;\n}\n\n<\/pre><\/div>\n\n\n

<\/p>\n\n\n\n


\n\n\n\n

9. \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:<\/p>\n\n\n\n

<\/p>\n\n\n\n

<\/p>\n\n\n\n

<\/p>\n\n\n\n

<\/p>\n\n\n\n


\n\n\n\n

<\/p>\n","protected":false},"excerpt":{"rendered":"

\u041f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 \u044d\u043a\u0440\u0430\u043d\u0430 \u043d\u0430\u0434\u043e \u043f\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0443 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0441\u0446\u0435\u043d\u0430 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043b\u0430 \u043d\u043e\u0432\u044b\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0446\u0435\u043d\u044b, \u0441\u043a\u0430\u0436\u0435\u043c, 500×300 (\u0447\u0442\u043e\u0431\u044b \u043a\u0443\u0431\u0438\u043a \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0441\u044f \u0432 \u044d\u043a\u0440\u0430\u043d). \u0423\u0433\u043e\u043b \u0437\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u0443 \u043d\u0430\u0441 30 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432. \u0437\u043d\u0430\u0447\u0438\u0442, ? \/ 250 = \u043a\u043e\u0441\u0438\u043d\u0443\u0441(15) \/ \u0441\u0438\u043d\u0443\u0441(15) = \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15) ? = 250 * \u043a\u043e\u0442\u0430\u043d\u0433\u0435\u043d\u0441(15) = 250 * 3.73 = […]<\/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-697","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\/697","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=697"}],"version-history":[{"count":9,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/posts\/697\/revisions"}],"predecessor-version":[{"id":1351,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/posts\/697\/revisions\/1351"}],"wp:attachment":[{"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/media?parent=697"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/categories?post=697"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.ru\/index.php\/wp-json\/wp\/v2\/tags?post=697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}