\n#pragma once\n#include "Coords.h"\n#include "linmath.h"\n\nclass Camera\n{\npublic:\n\tCoords ownCoords;\n\tmat4x4 lookAtMatrix;\n};\n\n<\/pre><\/div>\n\n\n<\/p>\n\n\n\n
\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0434\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0438 \u043e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043a\u0430\u043c\u0435\u0440\u044b. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043c\u0430\u0442\u0440\u0438\u0446\u0443 lookAtMatrix<\/em> \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043c\u0430\u0442\u0440\u0438\u0446\u0443 MVP (Model-View-Projection) \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0440\u0438\u043d\u0433\u0430.<\/p>\n\n\n\n\u0420\u0430\u0437\u043c\u0435\u0440\u044b \u043a\u0443\u0431\u0438\u043a\u0430 – 100x200x400 \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u044f – 0x0x0. \u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u043a\u0430\u043c\u0435\u0440\u0443 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u043e\u0442 \u043a\u0443\u0431\u0438\u043a\u0430 \u0431\u043b\u0438\u0436\u0435 \u043a \u043d\u0430\u043c, \u043d\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u044b\u0441\u043e\u0442\u0435 \u0447\u0442\u043e\u0431\u044b \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u043b\u0435\u0433\u043a\u0430 \u0441\u0432\u0435\u0440\u0445\u0443. \u041f\u043e\u0437\u0438\u0446\u0438\u044f 0x200x1000 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442.<\/p>\n\n\n\n
\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0437\u0433\u043b\u044f\u0434\u0430 (View direction) \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043e\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043a\u0430\u043c\u0435\u0440\u044b \u043a \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043a\u0443\u0431\u0438\u043a\u0430, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 0x-200x-1000.<\/p>\n\n\n\n
\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u0434\u0430\u0442\u044c view matrix \u043d\u0443\u0436\u043d\u044b: \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u0430\u043c\u0435\u0440\u044b (camera position), \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0437\u0433\u043b\u044f\u0434\u0430 (view direction), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u043b\u0438, \u0438 \u0432\u0435\u043a\u0442\u043e\u0440 \u043a\u0430\u043c\u0435\u0440\u044b \u0432\u0432\u0435\u0440\u0445 (camera UP vector), \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043a\u0430 \u043d\u0435\u0442, \u043d\u043e \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0437 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0437\u0433\u043b\u044f\u0434\u0430. \u0418\u0437 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0437\u0433\u043b\u044f\u0434\u0430 \u043c\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u043c \u0443\u0433\u043b\u044b \u043e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043a\u0430\u043c\u0435\u0440\u044b – \u0440\u044b\u0441\u043a\u0430\u043d\u044c\u0435 \u0438 \u0442\u0430\u043d\u0433\u0430\u0436 (yaw and pitch), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 180 \u0438 11.3 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432. \u041f\u043e \u043d\u0438\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c rotationMatrix<\/em> \u043a\u0430\u043c\u0435\u0440\u044b, \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0435\u0435 \u043a \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0432\u0435\u043a\u0442\u043e\u0440\u0443 0x1x0. \u0418 \u0442\u043e\u0433\u0434\u0430 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e mat4x4_look_at()<\/em> \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043c\u0430\u0442\u0440\u0438\u0446\u044b lookAtMatrix<\/em> \u0434\u043b\u044f \u043a\u0430\u043c\u0435\u0440\u044b.<\/p>\n\n\n\n\u0420\u0430\u0441\u0447\u0435\u0442\u044b yaw \u0438 pitch \u043c\u044b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0432 utils<\/strong>.<\/p>\n\n\n\n
\n\n\n\n4. \u041e\u0442\u043a\u0440\u043e\u0435\u043c utils.h<\/em> \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n\n#pragma once\n#include <string>\n#include "linmath.h"\n\nint checkGLerrors(std::string ref);\nvoid mat4x4_mul_vec4plus(vec4 vOut, mat4x4 M, vec4 vIn, int v3);\n\nvoid v3set(float* vOut, float x, float y, float z);\nvoid v3copy(float* vOut, float* vIn);\nfloat v3pitchRd(float* vIn);\nfloat v3yawRd(float* vIn);\nfloat v3pitchDg(float* vIn);\nfloat v3yawDg(float* vIn);\n\n<\/pre><\/div>\n\n\n<\/p>\n\n\n\n
\n\n\n\n5. \u041e\u0442\u043a\u0440\u043e\u0435\u043c utils.cpp<\/em> \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043a\u043e\u0434 \u043d\u0430:<\/p>\n\n\n\n#include "utils.h"\n#include "platform.h"\n\nextern float radians2degrees;\n\nint checkGLerrors(std::string ref) {\n \/\/can be used after any GL call\n int res = glGetError();\n if (res == 0)\n return 0;\n std::string errCode;\n switch (res) {\n \/\/case GL_NO_ERROR: errCode = "GL_NO_ERROR"; break;\n case GL_INVALID_ENUM: errCode = "GL_INVALID_ENUM"; break;\n case GL_INVALID_VALUE: errCode = "GL_INVALID_VALUE"; break;\n case GL_INVALID_OPERATION: errCode = "GL_INVALID_OPERATION"; break;\n case GL_INVALID_FRAMEBUFFER_OPERATION: errCode = "GL_INVALID_FRAMEBUFFER_OPERATION"; break;\n case GL_OUT_OF_MEMORY: errCode = "GL_OUT_OF_MEMORY"; break;\n default: errCode = "??"; break;\n }\n mylog("GL ERROR %d-%s in %s\\n", res, errCode.c_str(), ref.c_str());\n return -1;\n}\nvoid mat4x4_mul_vec4plus(vec4 vOut, mat4x4 M, vec4 vIn, int v3) {\n vec4 v2;\n if (vOut == vIn) {\n memcpy(&v2, vIn, sizeof(vec4));\n vIn = v2;\n }\n vIn[3] = (float)v3;\n mat4x4_mul_vec4(vOut, M, vIn);\n}\nvoid v3set(float* vOut, float x, float y, float z) {\n vOut[0] = x;\n vOut[1] = y;\n vOut[2] = z;\n}\nvoid v3copy(float* vOut, float* vIn) {\n for (int i = 0; i < 3; i++)\n vOut[i] = vIn[i];\n}\nfloat v3yawRd(float* vIn) {\n return atan2f(vIn[0], vIn[2]);\n}\nfloat v3pitchRd(float* vIn) {\n return -atan2f(vIn[1], sqrtf(vIn[0] * vIn[0] + vIn[2] * vIn[2]));\n}\nfloat v3pitchDg(float* vIn) { \n return v3pitchRd(vIn) * radians2degrees; \n}\nfloat v3yawDg(float* vIn) { \n return v3yawRd(vIn) * radians2degrees; \n}\n\n<\/pre><\/div>\n\n\n<\/p>\n\n\n\n
\n\n\n\n\u0412 TheGame.cpp<\/em> \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0440\u044f\u043c\u043e\u0439 \u043c\u0430\u0442\u0440\u0438\u0446\u044b mProjection <\/em>\u043c\u044b \u0437\u0430\u0434\u0430\u0434\u0438\u043c mProjection <\/em>\u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u044b <\/strong>\u0438 mViewProjection<\/em>, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f mProjection <\/em>\u043d\u0430 lookAtMatrix<\/em> \u043a\u0430\u043c\u0435\u0440\u044b.<\/p>\n\n\n\n\u0412\u044b\u0437\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043c\u0430\u0442\u0440\u0438\u0446\u044b mProjection \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u044b \u0442\u0430\u043a\u043e\u0439:<\/p>\n\n\n\n
mat4x4_perspective(mProjection, 3.14f \/ 6.0f, (float)screenSize[0]\/screenSize[1], 700.f, 1300.f);<\/em><\/p>\n\n\n\n\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n\n\n\n
- mProjection <\/em>– \u043a\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0443\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443<\/li>
- 3.14f \/ 6.0f<\/em> – \u0443\u0433\u043e\u043b \u0437\u0440\u0435\u043d\u0438\u044f, \u0432 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 – 30 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432 \u0432 \u0440\u0430\u0434\u0438\u0430\u043d\u0430\u0445<\/li>
- (float)screenSize[0]\/screenSize[1]<\/em> – screen size ratio<\/li>
- 700.f, 1300.f <\/em>– \u0431\u043b\u0438\u0436\u043d\u0438\u0439 \u0438 \u0434\u0430\u043b\u044c\u043d\u0438\u0439 \u043f\u043b\u0430\u043d\u044b<\/li><\/ul>\n\n\n\n
6. \u041e\u0442\u043a\u0440\u043e\u0435\u043c TheGame.cpp<\/em> \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u043c \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\nextern std::string filesRoot;\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.type.assign("box");\n vs.whl[0] = 100;\n vs.whl[1] = 200;\n vs.whl[2] = 400;\n\n Material mt;\n \/\/define material - flat red\n mt.shaderN = Shader::spN_flat_ucolor;\n mt.primitiveType = GL_TRIANGLES;\n mt.uColor.setRGBA(255, 0, 0,255); \/\/red\n pMB->useMaterial(&mt);\n\n pMB->buildBoxFace("front", &vs);\n pMB->buildBoxFace("back", &vs);\n pMB->buildBoxFace("top", &vs);\n pMB->buildBoxFace("bottom", &vs);\n pMB->buildBoxFace("left", &vs);\n\n mt.uColor.setRGBA(0, 0, 255,255); pMB->useMaterial(&mt); \/\/blue\n pMB->buildBoxFace("right", &vs);\n\n pMB->buildDrawJobs(gameSubjs);\n\n delete pMB;\n\n \/\/===== set up camera\n v3set(mainCamera.ownCoords.pos, 0, 200, 1000); \/\/set position\n float cameraDir[3];\n v3set(cameraDir, 0, -200, -1000); \/\/set direction vector\n float cameraYawDg = v3yawDg(cameraDir);\n float cameraPitchDg = v3pitchDg(cameraDir);\n mylog("cameraYaw=%f, cameraPitch=%f\\n", cameraYawDg, cameraPitchDg);\n\n mainCamera.ownCoords.setDegrees(cameraPitchDg, cameraYawDg, 0);\n float cameraUp[4] = { 0,1,0,0 }; \/\/y - up\n mat4x4_mul_vec4plus(cameraUp, *mainCamera.ownCoords.getRotationMatrix(), cameraUp, 0);\n\n mat4x4_look_at(mainCamera.lookAtMatrix, mainCamera.ownCoords.pos, pGS->ownCoords.pos, cameraUp);\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 mat4x4 mProjection, mViewProjection, mMVP;\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 mat4x4_perspective(mProjection, 3.14f \/ 6.0f, (float)screenSize[0] \/ screenSize[1], 700.f, 1300.f);\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 \/\/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, NULL);\n }\n }\n mySwapBuffers();\n return 1;\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 screenRatio = (float)width \/ (float)height;\n glViewport(0, 0, width, height);\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\nTheGame.h<\/em> \u0442\u043e\u0436\u0435 \u0441\u043b\u0435\u0433\u043a\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u044a\u0435\u043a\u0442 mainCamera<\/em>. <\/p>\n\n\n\n7. \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 screenRatio;\n\tbool bExitGame;\n\tCamera mainCamera;\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\n8. \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
<\/p>\n\n\n\n