Advertisement
Margoshinka

тела вращения

Mar 25th, 2023
914
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.77 KB | None | 0 0
  1. #pragma comment(lib, "opengl32.lib")
  2. #include <iostream>
  3. #include <Windows.h>
  4. #include <math.h>
  5. #include <vector>
  6.  
  7. #include <GL/glew.h>
  8. #include <GLFW/glfw3.h>
  9.  
  10. #include "matrix.h"
  11. #include "v3.h"
  12.  
  13. #include "stb_image.h"
  14. #include <string>
  15.  
  16. #include "glm/glm.hpp"
  17. #include "glm/gtc/matrix_transform.hpp"
  18. #include "glm/gtc/type_ptr.hpp"
  19.  
  20. using namespace std;
  21.  
  22. // Размерность сетки
  23. #define M 100
  24.  
  25. GLint w = 800, h = 600;
  26.  
  27. vector<pair<int, int>> coordClick;
  28.  
  29. const int countTextures = 2;
  30. bool drawing3DModel = false;
  31.  
  32.  
  33. // Окно
  34. GLFWwindow* g_window;
  35.  
  36. // Шейдерные программы
  37. GLuint g_shaderProgram, g_shaderProgramPoint, g_shaderProgramLine, g_shaderProgram3Dmodel;
  38.  
  39. #pragma region Идентификаторы юниформов
  40. GLint g_uMV;
  41. GLint g_uMVpoint;
  42. GLint g_uMV3Dmodel;
  43. GLint g_uP3Dmodel;
  44. GLint g_uMVP;
  45. GLint g_uN;
  46. GLint g_uL;
  47. GLint g_uP;
  48. #pragma endregion
  49.  
  50. // Класс модели
  51. class Model
  52. {
  53. public:
  54.     GLuint vbo;
  55.     GLuint ibo;
  56.     GLuint vao;
  57.     GLsizei indexCount;
  58. } g_model, g_modelPoint, g_modelLine, g_modelSurface;
  59.  
  60. // Структура текстуры
  61. struct Texture
  62. {
  63.     const GLchar* fileImageName;        // Имя файла с картинкой
  64.     const GLchar* uniformMapName;       // Имя юниформа
  65.     GLint mapLocation;                  // Идентификатор юниформа
  66.     GLint texUnit;
  67.  
  68.     Texture(const GLchar* fileImageName, const GLchar* uniformMapName, GLint texUnit)
  69.     {
  70.         this->fileImageName = fileImageName;
  71.         this->uniformMapName = uniformMapName;
  72.         this->texUnit = texUnit;
  73.     }
  74. };
  75.  
  76. // Структура точки
  77. struct point
  78. {
  79.     double x, y;
  80.     point(double x, double y)
  81.     {
  82.         this->x = x;
  83.         this->y = y;
  84.     }
  85. };
  86.  
  87. vector<point> points, bezierPoints, normals;
  88.  
  89.  
  90. Texture textures[countTextures] =
  91. {
  92.     Texture("1.jpg", "u_map1", 0),
  93.     Texture("2.jpg", "u_map2", 1)
  94. };
  95.  
  96. // Массив индексов (имен) текстур
  97. GLuint texIDs[countTextures];
  98.  
  99. void createTexture(const GLchar* nameFile, GLint texID)
  100. {
  101.     GLint texW, texH, numComponents;
  102.  
  103.     // Берем указатель на данные изображения в памяти
  104.     GLvoid* imageData = stbi_load(nameFile, &texW, &texH, &numComponents, 4);
  105.  
  106.     // Привязка текстуры к цели текстурирования
  107.     glBindTexture(GL_TEXTURE_2D, texID);
  108.  
  109.     // Задаем изображение текстуры
  110.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texW, texH, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
  111.  
  112.     stbi_image_free(imageData);
  113.  
  114.     // Задаем параметры текстуры
  115.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  116.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  117.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  118.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  119. }
  120.  
  121. void initTextures()
  122. {
  123.     // Генерируем id для текстур и сохраняем их в массив
  124.     glGenTextures(2, texIDs);
  125.  
  126.     for (int i = 0; i < countTextures; i++)
  127.     {
  128.         createTexture(textures[i].fileImageName, texIDs[i]);
  129.         textures[i].mapLocation = glGetUniformLocation(g_shaderProgram, textures[i].uniformMapName);
  130.     }
  131. }
  132.  
  133. GLuint createShader(const GLchar* code, GLenum type)
  134. {
  135.     GLuint result = glCreateShader(type);
  136.  
  137.     glShaderSource(result, 1, &code, NULL);
  138.     glCompileShader(result);
  139.  
  140.     GLint compiled;
  141.     glGetShaderiv(result, GL_COMPILE_STATUS, &compiled);
  142.  
  143.     if (!compiled)
  144.     {
  145.         GLint infoLen = 0;
  146.         glGetShaderiv(result, GL_INFO_LOG_LENGTH, &infoLen);
  147.         if (infoLen > 0)
  148.         {
  149.             char* infoLog = new char[infoLen];
  150.             glGetShaderInfoLog(result, infoLen, NULL, infoLog);
  151.             cout << "Shader compilation error" << endl << infoLog << endl;
  152.         }
  153.         glDeleteShader(result);
  154.         return 0;
  155.     }
  156.  
  157.     return result;
  158. }
  159.  
  160. GLuint createProgram(GLuint vsh, GLuint fsh)
  161. {
  162.     GLuint result = glCreateProgram();
  163.  
  164.     glAttachShader(result, vsh);
  165.     glAttachShader(result, fsh);
  166.  
  167.     glLinkProgram(result);
  168.  
  169.     GLint linked;
  170.     glGetProgramiv(result, GL_LINK_STATUS, &linked);
  171.  
  172.     if (!linked)
  173.     {
  174.         GLint infoLen = 0;
  175.         glGetProgramiv(result, GL_INFO_LOG_LENGTH, &infoLen);
  176.         if (infoLen > 0)
  177.         {
  178.             char* infoLog = (char*)alloca(infoLen);
  179.             glGetProgramInfoLog(result, infoLen, NULL, infoLog);
  180.             cout << "Shader program linking error" << endl << infoLog << endl;
  181.         }
  182.         glDeleteProgram(result);
  183.         return 0;
  184.     }
  185.  
  186.     return result;
  187. }
  188.  
  189. bool createShaderProgram()
  190. {
  191.     // Шейдеры для точки
  192.  
  193.     g_shaderProgramPoint = 0;
  194.  
  195.     const GLchar vshP[] =
  196.         "#version 330\n"
  197.         ""
  198.         "layout(location = 0) in vec2 a_position;"
  199.         ""
  200.         "uniform mat4 u_MV;"
  201.         ""
  202.         "void main()"
  203.         "{"
  204.         "    gl_Position = u_MV * vec4(a_position, 0.0, 1.0);"
  205.         "}"
  206.         ;
  207.  
  208.     const GLchar fshP[] =
  209.         "#version 330\n"
  210.         ""
  211.         "layout(location = 0) out vec4 o_color;"
  212.         ""
  213.         "void main()"
  214.         "{"
  215.         "   o_color = vec4(1.0, 0.0, 0.0, 0.0);"
  216.         "}"
  217.         ;
  218.  
  219.     GLuint vertexShader, fragmentShader;
  220.  
  221.     vertexShader = createShader(vshP, GL_VERTEX_SHADER);
  222.     fragmentShader = createShader(fshP, GL_FRAGMENT_SHADER);
  223.  
  224.     g_shaderProgramPoint = createProgram(vertexShader, fragmentShader);
  225.     g_uMVpoint = glGetUniformLocation(g_shaderProgramPoint, "u_MV");
  226.  
  227.     glDeleteShader(vertexShader);
  228.     glDeleteShader(fragmentShader);
  229.  
  230.     // Шейдер для кривой
  231.  
  232.     g_shaderProgramLine = 0;
  233.  
  234.     const GLchar vshL[] =
  235.         "#version 330\n"
  236.         ""
  237.         "layout(location = 0) in vec2 a_position;"
  238.         ""
  239.         "void main()"
  240.         "{"
  241.         "    gl_Position = vec4(a_position, 0.0, 1.0);"
  242.         "}"
  243.         ;
  244.  
  245.     const GLchar fshL[] =
  246.         "#version 330\n"
  247.         ""
  248.         "layout(location = 0) out vec4 o_color;"
  249.         ""
  250.         "void main()"
  251.         "{"
  252.         "   o_color = vec4(0.0, 0.0, 0.0, 0.0);"
  253.         "}"
  254.         ;
  255.  
  256.     vertexShader = createShader(vshL, GL_VERTEX_SHADER);
  257.     fragmentShader = createShader(fshL, GL_FRAGMENT_SHADER);
  258.  
  259.     g_shaderProgramLine = createProgram(vertexShader, fragmentShader);
  260.  
  261.     glDeleteShader(vertexShader);
  262.     glDeleteShader(fragmentShader);
  263.  
  264.     g_shaderProgram = 0;
  265.  
  266.     const GLchar vsh[] =
  267.         "#version 330\n"
  268.         ""
  269.         "layout(location = 0) in vec2 a_position;"
  270.         "layout(location = 1) in vec2 a_texCoord;"
  271.         ""
  272.         "uniform mat4 u_mv;"
  273.         "uniform mat4 u_mvp;"
  274.         "uniform mat3 u_n;"
  275.         ""
  276.         "out vec3 v_p;"
  277.         "out vec3 v_normal;"
  278.         "out vec2 v_texCoord;"
  279.         ""
  280.         "void main()"
  281.         "{"
  282.         "   v_texCoord = a_texCoord;"
  283.         "   vec4 pos = vec4(a_position[0], sin(a_position[0]*10)*sin(a_position[1]*10)/5, a_position[1], 1);"
  284.         "   gl_Position = u_mvp * pos;"
  285.         "   v_p = (u_mv * pos).xyz;"
  286.         "   v_normal = normalize(u_n*vec3(-cos(10*a_position[0])*sin(10*a_position[1]), 1.0, -cos(10*a_position[1])*sin(10*a_position[0])));"
  287.         "}"
  288.         ;
  289.  
  290.     const GLchar fsh[] =
  291.         "#version 330\n"
  292.         ""
  293.         "in vec3 v_p;"
  294.         "in vec3 v_normal;"
  295.         "in vec2 v_texCoord;"
  296.         ""
  297.         "layout(location = 0) out vec4 o_color;"
  298.         ""
  299.         "uniform vec3 u_l;"
  300.         ""
  301.         "uniform sampler2D u_map1;"
  302.         "uniform sampler2D u_map2;"
  303.         ""
  304.         "void main()"
  305.         "{"
  306.         "   vec3 n = normalize(v_normal);"
  307.         "   vec3 l = normalize(v_p-u_l);"
  308.         "   float cosa = dot(-l, n);"
  309.         "   float d = max(cosa, 0.1);"
  310.         "   vec3 r = reflect(l, n);"
  311.         "   vec3 e = normalize(-v_p);"
  312.         "   float b = max(dot(r, e), 0.0); "
  313.         "   float s = pow(b, 5.0) * int(cosa >= 0);"
  314.         "   o_color = vec4(d*mix(texture(u_map1, v_texCoord), texture(u_map2, v_texCoord), 0.5).xyz + s * vec3(1.0), 1.0);"
  315.         "}"
  316.         ;
  317.  
  318.     vertexShader = createShader(vsh, GL_VERTEX_SHADER);
  319.     fragmentShader = createShader(fsh, GL_FRAGMENT_SHADER);
  320.  
  321.     g_shaderProgram = createProgram(vertexShader, fragmentShader);
  322.  
  323.     //Запрашиваем соответствующий идентификатор по имени юниформа
  324.     g_uMVP = glGetUniformLocation(g_shaderProgram, "u_mvp");
  325.     g_uMV = glGetUniformLocation(g_shaderProgram, "u_mv");
  326.     g_uN = glGetUniformLocation(g_shaderProgram, "u_n");
  327.     g_uL = glGetUniformLocation(g_shaderProgram, "u_l");
  328.  
  329.     glDeleteShader(vertexShader);
  330.     glDeleteShader(fragmentShader);
  331.  
  332.     initTextures();
  333.  
  334.     g_shaderProgram3Dmodel = 0;
  335.  
  336. #pragma region s
  337.     const GLchar vshM[] =
  338.         "#version 330\n"
  339.         ""
  340.         "layout(location = 0) in vec3 a_position;"
  341.         "layout(location = 1) in vec3 a_norm;"
  342.         "uniform mat4 u_P;"
  343.         "uniform mat4 u_MV;"
  344.         "out vec3 v_point;"
  345.         "out vec3 v_norm;"
  346.         ""
  347.         "void main()"
  348.         "{"
  349.         "    v_norm = transpose(inverse(mat3(u_MV))) * a_norm;"
  350.         "    v_norm = v_norm/length(v_norm);"
  351.         "    v_point = vec3(u_MV * vec4(a_position, 1.0));"
  352.         "    gl_Position = u_P * u_MV * vec4(a_position, 1.0);"
  353.         "}"
  354.         ;
  355.  
  356.     const GLchar fshM[] =
  357.         "#version 330\n"
  358.         ""
  359.         "layout(location = 0) out vec4 o_color;"
  360.         "in vec3 v_point;"
  361.         "in vec3 v_norm;"
  362.         ""
  363.         "void main()"
  364.         "{"
  365.         "   vec3 viewDir = v_point - vec3(0.0);"
  366.         "   viewDir = normalize(viewDir);"
  367.         "   vec3 v_norm_good = v_norm;"
  368.         "   if (dot(-v_norm,viewDir) < dot(v_norm,viewDir)) v_norm_good = - v_norm;"
  369.         "   vec3 ambientColor = vec3(0.3);"
  370.         "   vec3 lightDir = v_point - vec3(7, 7, 7);"
  371.         "   lightDir = normalize(lightDir);"
  372.         "   float diff = dot(v_norm_good, -lightDir);"
  373.         "   diff = max(diff, 0.0);"
  374.         "   vec3 diffColor = diff*vec3(1.0, 1.0, 1.0);"
  375.         "   vec3 reflectDir = reflect(lightDir, v_norm_good);"
  376.         "   float spec = dot(reflectDir, -viewDir);"
  377.         "   spec = max(spec, 0.0);"
  378.         "   if (dot(v_norm_good,reflectDir) < 0) spec = 0;"
  379.         "   vec3 specColor = pow(spec, 20.0) * vec3(1.0, 1.0, 1.0);"
  380.         "   vec3 resultColor = (ambientColor + diffColor + specColor) * vec3(0.4, 0.5, 0);"
  381.         "   o_color = vec4(resultColor, 1.0);"
  382.         "}"
  383.         ;
  384.  
  385.     GLuint vertexShaderM, fragmentShaderM;
  386.  
  387.     vertexShaderM = createShader(vshM, GL_VERTEX_SHADER);
  388.     fragmentShaderM = createShader(fshM, GL_FRAGMENT_SHADER);
  389.  
  390.     g_shaderProgram3Dmodel = createProgram(vertexShaderM, fragmentShaderM);
  391.  
  392.     g_uMV3Dmodel = glGetUniformLocation(g_shaderProgram3Dmodel, "u_MV");
  393.     g_uP3Dmodel = glGetUniformLocation(g_shaderProgram3Dmodel, "u_P");
  394.     glDeleteShader(vertexShaderM);
  395.     glDeleteShader(fragmentShaderM);
  396. #pragma endregion
  397.     return g_shaderProgram != 0 && g_shaderProgramPoint != 0;
  398. }
  399.  
  400. bool createModelPoint()
  401. {
  402.     const GLfloat vertices[] =
  403.     {
  404.         -0.3f, -0.5f,
  405.         0.5f, -0.5f,
  406.         0.5f,  0.5f,
  407.         -0.3f,  0.5f,
  408.     };
  409.  
  410.     const GLuint indices[] =
  411.     {
  412.         0, 1, 2, 2, 3, 0
  413.     };
  414.     glGenVertexArrays(1, &g_modelPoint.vao);
  415.     glBindVertexArray(g_modelPoint.vao);
  416.  
  417.     glGenBuffers(1, &g_modelPoint.vbo);
  418.     glBindBuffer(GL_ARRAY_BUFFER, g_modelPoint.vbo);
  419.     glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
  420.  
  421.     glGenBuffers(1, &g_modelPoint.ibo);
  422.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_modelPoint.ibo);
  423.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);
  424.     g_modelPoint.indexCount = 6;
  425.  
  426.     glEnableVertexAttribArray(0);
  427.     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (const GLvoid*)0);
  428.  
  429.     return g_modelPoint.vbo != 0 && g_modelPoint.ibo != 0 && g_modelPoint.vao != 0;
  430. }
  431.  
  432. bool createModelLine()
  433. {
  434.     GLfloat* pointsToDraw = new GLfloat[bezierPoints.size() * 2];
  435.     GLuint* indices = new GLuint[bezierPoints.size()];
  436.     int i = 0;
  437.     for (point p : bezierPoints)
  438.     {
  439.         pointsToDraw[i] = p.x;
  440.         pointsToDraw[i + 1] = p.y;
  441.         indices[i / 2] = i / 2;
  442.         i = i + 2;
  443.     }
  444.     glGenVertexArrays(1, &g_modelLine.vao);
  445.     glBindVertexArray(g_modelLine.vao);
  446.  
  447.     glGenBuffers(1, &g_modelLine.vbo);
  448.     glBindBuffer(GL_ARRAY_BUFFER, g_modelLine.vbo);
  449.     glBufferData(GL_ARRAY_BUFFER, 2 * bezierPoints.size() * sizeof(GLfloat), pointsToDraw, GL_STATIC_DRAW);
  450.  
  451.     glGenBuffers(1, &g_modelLine.ibo);
  452.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_modelLine.ibo);
  453.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, bezierPoints.size() * sizeof(GLuint), indices, GL_STATIC_DRAW);
  454.     g_modelLine.indexCount = bezierPoints.size();
  455.  
  456.  
  457.     glEnableVertexAttribArray(0);
  458.     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (const GLvoid*)0);
  459.  
  460.     delete[] pointsToDraw;
  461.  
  462.     return g_modelLine.vbo != 0 && g_modelLine.ibo != 0 && g_modelLine.vao != 0;
  463. }
  464.  
  465. bool create3DModel()
  466. {
  467.     GLfloat* pointsToDraw = new GLfloat[bezierPoints.size() * 6 * (N + 1)];
  468.     GLuint* indices = new GLuint[bezierPoints.size() * N * 6];
  469.     for (int k = 0; k <= N; k++)
  470.     {
  471.         glm::mat4 transb = glm::translate(glm::mat4(1.0), glm::vec3(0.0f, -1.0f, 0.0f));
  472.         glm::mat4 trans = glm::translate(glm::mat4(1.0), glm::vec3(0.0f, 1.0f, 0.0f));
  473.         glm::mat4 rotate = glm::rotate(glm::mat4(1.0), glm::radians((float)k * 360 / N), glm::vec3(1.0, 0.0, 0.0)) * trans;
  474.         glm::mat3 rotateNorm = glm::transpose(glm::inverse(glm::mat3(rotate)));
  475.         for (int i = 0; i < bezierPoints.size(); i++)
  476.         {
  477.             glm::vec4 resultPos = rotate * glm::vec4(bezierPoints[i].x, bezierPoints[i].y, 0, 1);
  478.             glm::vec3 resultNorm = rotateNorm * glm::vec3(normals[i].x, normals[i].y, 0);
  479.             pointsToDraw[k * 6 * bezierPoints.size() + 6 * i] = resultPos.x;
  480.             pointsToDraw[k * 6 * bezierPoints.size() + 6 * i + 1] = resultPos.y;
  481.             pointsToDraw[k * 6 * bezierPoints.size() + 6 * i + 2] = resultPos.z;
  482.             pointsToDraw[k * 6 * bezierPoints.size() + 6 * i + 3] = resultNorm.x;
  483.             pointsToDraw[k * 6 * bezierPoints.size() + 6 * i + 4] = resultNorm.y;
  484.             pointsToDraw[k * 6 * bezierPoints.size() + 6 * i + 5] = resultNorm.z;
  485.         }
  486.     }
  487.     for (int k = 0; k < N; k++)
  488.     {
  489.         for (int i = 0; i < bezierPoints.size() - 1; i++)
  490.         {
  491.             indices[k * 6 * bezierPoints.size() + i * 6] = k * bezierPoints.size() + (i);
  492.             indices[k * 6 * bezierPoints.size() + i * 6 + 1] = k * bezierPoints.size() + (i + 1);
  493.             indices[k * 6 * bezierPoints.size() + i * 6 + 2] = (k + 1) * bezierPoints.size() + (i);
  494.             indices[k * 6 * bezierPoints.size() + i * 6 + 3] = (k + 1) * bezierPoints.size() + (i);
  495.             indices[k * 6 * bezierPoints.size() + i * 6 + 4] = (k + 1) * bezierPoints.size() + (i + 1);
  496.             indices[k * 6 * bezierPoints.size() + i * 6 + 5] = k * bezierPoints.size() + (i + 1);
  497.         }
  498.     }
  499.     glGenVertexArrays(1, &g_modelSurface.vao);
  500.     glBindVertexArray(g_modelSurface.vao);
  501.  
  502.     glGenBuffers(1, &g_modelSurface.vbo);
  503.     glBindBuffer(GL_ARRAY_BUFFER, g_modelSurface.vbo);
  504.     glBufferData(GL_ARRAY_BUFFER, bezierPoints.size() * 6 * (N + 1) * sizeof(GLfloat), pointsToDraw, GL_STATIC_DRAW);
  505.  
  506.     glGenBuffers(1, &g_modelSurface.ibo);
  507.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_modelSurface.ibo);
  508.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, bezierPoints.size() * N * 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);
  509.     g_modelSurface.indexCount = bezierPoints.size() * N * 6;
  510.  
  511.     glEnableVertexAttribArray(0);
  512.     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (const GLvoid*)0);
  513.     glEnableVertexAttribArray(1);
  514.     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat)));
  515.  
  516.  
  517.     delete[] pointsToDraw;
  518.     delete[] indices;
  519.     return g_modelSurface.vbo != 0 && g_modelSurface.ibo != 0 && g_modelSurface.vao != 0;
  520. }
  521.  
  522. bool createModel()
  523. {
  524.     GLfloat vertices[(M + 1) * (M + 1) * 4];
  525.  
  526.     int k = 0;
  527.     for (int i = 0; i <= M; i++)
  528.     {
  529.         for (int j = 0; j <= M; j += 1)
  530.         {
  531.             vertices[k++] = GLfloat(j) / M;
  532.             vertices[k++] = GLfloat(i) / M;
  533.             vertices[k++] = GLfloat(j) / M;
  534.             vertices[k++] = GLfloat(i) / M;
  535.         }
  536.     }
  537.     GLuint indices[M * M * 6];
  538.     k = 0;
  539.     for (int i = 0; i < M; i++)
  540.     {
  541.         for (int j = 0; j < M; j++)
  542.         {
  543.             indices[k++] = (M + 1) * i + j;
  544.             indices[k++] = (M + 1) * i + j + 1;
  545.             indices[k++] = (M + 1) * i + j + M + 2;
  546.             indices[k++] = (M + 1) * i + j + M + 2;
  547.             indices[k++] = (M + 1) * i + j + M + 1;
  548.             indices[k++] = (M + 1) * i + j;
  549.         }
  550.     }
  551.  
  552.     glGenVertexArrays(1, &g_model.vao);
  553.     glBindVertexArray(g_model.vao);
  554.  
  555.     glGenBuffers(1, &g_model.vbo);
  556.     glBindBuffer(GL_ARRAY_BUFFER, g_model.vbo);
  557.     glBufferData(GL_ARRAY_BUFFER, (M + 1) * (M + 1) * 4 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
  558.  
  559.     glGenBuffers(1, &g_model.ibo);
  560.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_model.ibo);
  561.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, M * M * 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);
  562.  
  563.     g_model.indexCount = M * M * 6;
  564.  
  565.     glEnableVertexAttribArray(0);
  566.     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (const GLvoid*)0);
  567.     glEnableVertexAttribArray(1);
  568.     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (const GLvoid*)(2 * sizeof(GLfloat)));
  569.  
  570.     return g_model.vbo != 0 && g_model.ibo != 0 && g_model.vao != 0;
  571. }
  572.  
  573. bool init()
  574. {
  575.     // Set initial color of color buffer to white.
  576.     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  577.  
  578.     //Включение теста глубины. При выключеном куб выворачивается наизнанку
  579.     glEnable(GL_DEPTH_TEST);
  580.  
  581.     // Разрешает наложение текстуры
  582.     glEnable(GL_TEXTURE_2D);
  583.  
  584.     //glEnable(GL_CULL_FACE);
  585.  
  586.     return createShaderProgram() && createModel() && createModelPoint();
  587. }
  588.  
  589. void reshape(GLFWwindow* window, int width, int height)
  590. {
  591.     glViewport(0, 0, width, height);
  592. }
  593.  
  594. void draw(float ax, float ay, float az, float ey, float ez, float ly, float lz)
  595. {
  596.     GLint w, h = 0;
  597.     glfwGetWindowSize(g_window, &w, &h);
  598.  
  599.     // очистка буфера цвета и очистка буфера глубины
  600.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  601.  
  602.     // Включаем шейдерную программу
  603.     glUseProgram(g_shaderProgram);
  604.  
  605.     // Биндим модель
  606.     glBindVertexArray(g_model.vao);
  607.  
  608.     matrix model = matrix::getModelMatrix();
  609.  
  610.     matrix view = matrix::getViewMatrix(
  611.         v3(3, ey, ez),              // Точка E, определяющая позицию наблюдателя на сцене.
  612.         v3(0, 0, 0),                // Точка C, определяющая центр видимой области.
  613.         v3(0, 1, 0)                 // Вектор u, определяющий направление «вверх» для наблюдателя.
  614.     );
  615.     //matrix projection = matrix::getPparMatrix(0, w, 0, h, -1, 1);
  616.     matrix projection = matrix::getPperspMatrix(
  617.         0.1,                        // Ближняя плоскость отсечения. Должна быть больше 0.
  618.         100.,                       // Дальняя плоскость отсечения.  
  619.         w, h,                       // Ширина и высота окна
  620.         45.                         // Угол обзора
  621.     );
  622.  
  623.     model = matrix::scale(model, v3(2, 2, 2));
  624.     model = matrix::translate(model, v3(-0.5, 0, 0));
  625.     model = matrix::rotate(model, ax, v3(1, 0, 0));
  626.     model = matrix::rotate(model, ay + 45, v3(0, 1, 0));
  627.     model = matrix::rotate(model, az, v3(0, 0, 1));
  628.  
  629.     matrix mv = view * model;
  630.     matrix mvp = projection * mv;
  631.  
  632.     GLfloat n[9];
  633.     memcpy(n, matrix::getInvMatrixNotTranspose(mv), 9 * sizeof(GLfloat));
  634.  
  635.     glUniformMatrix4fv(g_uMVP, 1, GL_FALSE, mvp.get_value());
  636.     glUniformMatrix4fv(g_uMV, 1, GL_FALSE, mv.get_value());
  637.     glUniformMatrix3fv(g_uN, 1, GL_FALSE, n);
  638.  
  639.     // Положение источника света
  640.     GLfloat  l[3]{ 0, ly, lz };
  641.     glUniform3fv(g_uL, 1, l);
  642.  
  643.     for (int i = 0; i < countTextures; i++)
  644.     {
  645.         glActiveTexture(GL_TEXTURE0 + textures[i].texUnit);
  646.         glBindTexture(GL_TEXTURE_2D, texIDs[i]);
  647.         glUniform1i(textures[i].mapLocation, textures[i].texUnit);
  648.     }
  649.  
  650.     // Запускаем отрисовку и отображаем на экран
  651.     glDrawElements(GL_TRIANGLES, g_model.indexCount, GL_UNSIGNED_INT, NULL);
  652.  
  653.  
  654.     if (drawing3DModel)
  655.     {
  656.         glUseProgram(g_shaderProgram3Dmodel);
  657.         //glBindBuffer(GL_ARRAY_BUFFER, m_model.vbo);
  658.         //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_model.ibo);
  659.         glBindVertexArray(g_modelSurface.vao);
  660.  
  661.         glm::mat4 P = glm::perspective(45.0f, (GLfloat)800.0f / (GLfloat)600.0f, 0.1f, 100.0f);
  662.         glm::mat4 f = glm::translate(glm::mat4(1.0), glm::vec3(0.0f, 1.0f, 0.0f));
  663.         glm::mat4 trans = glm::translate(glm::mat4(1.0), glm::vec3(0.0f, 0.0f, -5.0f));
  664.         glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(1));
  665.         glm::mat4 rotate = glm::rotate(glm::mat4(1.0), glm::radians(30.0f), glm::vec3(1.0f, 1.0f, 0.0f));
  666.         glm::mat4 rotating = glm::rotate(glm::mat4(1.0), (GLfloat)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
  667.         glm::mat4 view = trans * scale * rotate * rotating;
  668.         glUniformMatrix4fv(g_uP3Dmodel, 1, GL_FALSE, glm::value_ptr(P));
  669.         glUniformMatrix4fv(g_uMV3Dmodel, 1, GL_FALSE, glm::value_ptr(view));
  670.         glDrawElements(GL_TRIANGLES, g_modelSurface.indexCount, GL_UNSIGNED_INT, NULL);
  671.         return;
  672.     }
  673.  
  674.     // Рисуем точки
  675.     glUseProgram(g_shaderProgramPoint);
  676.     glBindVertexArray(g_modelPoint.vao);
  677.  
  678.     for (point p : points)
  679.     {
  680.         matrix view = matrix::translate(matrix(1.0), v3(p.x, p.y, 0.0f));
  681.         view = matrix::scale(view, v3(0.01, 0.01, 0.01));
  682.         glUniformMatrix4fv(g_uMVpoint, 1, GL_FALSE, view.get_value());
  683.         glDrawElements(GL_TRIANGLES, g_modelPoint.indexCount, GL_UNSIGNED_INT, NULL);
  684.     }
  685.  
  686.     // Рисуем линию
  687.     glUseProgram(g_shaderProgramLine);
  688.     glBindVertexArray(g_modelLine.vao);
  689.     glDrawElements(GL_LINE_STRIP, g_modelLine.indexCount, GL_UNSIGNED_INT, NULL);
  690. }
  691.  
  692. void cleanup()
  693. {
  694.     if (g_shaderProgram != 0)
  695.         glDeleteProgram(g_shaderProgram);
  696.     if (g_model.vbo != 0)
  697.         glDeleteBuffers(1, &g_model.vbo);
  698.     if (g_model.ibo != 0)
  699.         glDeleteBuffers(1, &g_model.ibo);
  700.     if (g_model.vao != 0)
  701.         glDeleteVertexArrays(1, &g_model.vao);
  702.  
  703.     glDeleteTextures(countTextures, texIDs);
  704. }
  705.  
  706. bool initOpenGL()
  707. {
  708.     // Initialize GLFW functions.
  709.     if (!glfwInit())
  710.     {
  711.         cout << "Failed to initialize GLFW" << endl;
  712.         return false;
  713.     }
  714.  
  715.     // Request OpenGL 3.3 without obsoleted functions.
  716.     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  717.     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  718.     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  719.     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  720.  
  721.     // Create window.
  722.     g_window = glfwCreateWindow(800, 600, "OpenGL Test", NULL, NULL);
  723.     if (g_window == NULL)
  724.     {
  725.         cout << "Failed to open GLFW window" << endl;
  726.         glfwTerminate();
  727.         return false;
  728.     }
  729.  
  730.     // Initialize OpenGL context with.
  731.     glfwMakeContextCurrent(g_window);
  732.  
  733.     // Set internal GLEW variable to activate OpenGL core profile.
  734.     glewExperimental = true;
  735.  
  736.     // Initialize GLEW functions.
  737.     if (glewInit() != GLEW_OK)
  738.     {
  739.         cout << "Failed to initialize GLEW" << endl;
  740.         return false;
  741.     }
  742.  
  743.     // Ensure we can capture the escape key being pressed.
  744.     glfwSetInputMode(g_window, GLFW_STICKY_KEYS, GL_TRUE);
  745.  
  746.     // Set callback for framebuffer resizing event.
  747.     glfwSetFramebufferSizeCallback(g_window, reshape);
  748.  
  749.     return true;
  750. }
  751.  
  752. void tearDownOpenGL()
  753. {
  754.     // Terminate GLFW.
  755.     glfwTerminate();
  756. }
  757.  
  758. pair<vector<float>, vector<float>> computeControlPoints(vector<float> K)
  759. {
  760.     int n = K.size() - 1;
  761.  
  762.     vector<float> p1(n), p2(n);
  763.  
  764.     /*rhs vector*/
  765.     vector<float> a(n), b(n), c(n), r(n);
  766.  
  767.     /*left most segment*/
  768.     a[0] = 0;
  769.     b[0] = 2;
  770.     c[0] = 1;
  771.     r[0] = K[0] + 2 * K[1];
  772.  
  773.     /*internal segments*/
  774.     for (int i = 1; i < n - 1; i++)
  775.     {
  776.         a[i] = 1;
  777.         b[i] = 4;
  778.         c[i] = 1;
  779.         r[i] = 4 * K[i] + 2 * K[i + 1];
  780.     }
  781.  
  782.     /*right segment*/
  783.     a[n - 1] = 2;
  784.     b[n - 1] = 7;
  785.     c[n - 1] = 0;
  786.     r[n - 1] = 8 * K[n - 1] + K[n];
  787.     float m;
  788.  
  789.     /*solves Ax=b with the Thomas algorithm (from Wikipedia)*/
  790.     for (int i = 1; i < n; i++)
  791.     {
  792.         m = a[i] / b[i - 1];
  793.         b[i] = b[i] - m * c[i - 1];
  794.         r[i] = r[i] - m * r[i - 1];
  795.     }
  796.  
  797.     p1[n - 1] = r[n - 1] / b[n - 1];
  798.     for (int i = n - 2; i >= 0; --i)
  799.         p1[i] = (r[i] - c[i] * p1[i + 1]) / b[i];
  800.  
  801.     /*we have p1, now compute p2*/
  802.     for (int i = 0; i < n - 1; i++)
  803.         p2[i] = 2 * K[i + 1] - p1[i + 1];
  804.  
  805.     p2[n - 1] = 0.5 * (K[n] + p1[n - 1]);
  806.  
  807.     return make_pair(p1, p2);
  808. }
  809.  
  810. // Вычисление факториала
  811. int factorial(int n)
  812. {
  813.     int res = 1;
  814.     for (int i = 1; i <= n; i++)
  815.         res *= i;
  816.     return res;
  817. }
  818.  
  819. // Кривая Безье (полином B(t))
  820. float polinom(int i, int n, float t)// Функция вычисления полинома Бернштейна
  821. {
  822.     return (factorial(n) / (factorial(i) * factorial(n - i))) * (float)pow(t, i) * (float)pow(1 - t, n - i);
  823. }
  824.  
  825. vector<point> computeBezierPoints(vector<float> pointsX, vector<float> pointsY,
  826.     pair<vector<float>, vector<float>> controlPointsX, pair<vector<float>, vector<float>> controlPointsY)
  827. {
  828.     vector<point> bezierPoints;
  829.     // compute bezier points
  830.     int j = 0;
  831.     float step = 0.02f;// Возьмем шаг 0.01 для большей точности
  832.     for (int i = 0; i < points.size() - 1; i++)
  833.         for (float t = 0; t < 1; t += step)
  834.         {
  835.             float ytmp = 0;
  836.             float xtmp = 0;
  837.             // проходим по каждой точке
  838.             // вычисляем наш полином Берштейна
  839.             float b = polinom(0, 3, t);
  840.             xtmp += pointsX[i] * b;
  841.             ytmp += pointsY[i] * b;
  842.             b = polinom(1, 3, t);
  843.             xtmp += get<0>(controlPointsX)[i] * b;
  844.             ytmp += get<0>(controlPointsY)[i] * b;
  845.             b = polinom(2, 3, t);
  846.             xtmp += get<1>(controlPointsX)[i] * b;
  847.             ytmp += get<1>(controlPointsY)[i] * b;
  848.             b = polinom(3, 3, t);
  849.             xtmp += pointsX[i + 1] * b;
  850.             ytmp += pointsY[i + 1] * b;
  851.             bezierPoints.push_back(point(xtmp, ytmp));
  852.             j++;
  853.         }
  854.     return bezierPoints;
  855. }
  856.  
  857.  
  858.  
  859. void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
  860. {
  861.     if (action == GLFW_PRESS)
  862.     {
  863.         // ширина, высота окнаю
  864.         int w = 0, h = 0;
  865.  
  866.         // координаты клика
  867.         double xpos, ypos;
  868.  
  869.         // Получаем соответвующие характеристики
  870.         glfwGetCursorPos(g_window, &xpos, &ypos);
  871.         glfwGetWindowSize(g_window, &w, &h);
  872.  
  873.         // Пересчитываем координаты в соответствии с NDC (норированные координаты устройства)
  874.         xpos = xpos / w * 2. - 1.;
  875.         ypos = 1. - ypos / h * 2.;
  876.  
  877.         cout << "Coord click: (" << xpos << ", " << ypos << ")" << endl;
  878.         points.push_back(point(xpos, ypos));
  879.  
  880.         // Очищаем список точек для кривой Безье (т.к. придется перестраивать)
  881.         bezierPoints.clear();
  882.         if (points.size() < 2)
  883.             return;
  884.         if (points.size() == 2)
  885.         {
  886.             bezierPoints = points;
  887.             createModelLine();
  888.             return;
  889.         }
  890.  
  891.         vector<float> pointsX, pointsY;
  892.  
  893.         for (point p : points)
  894.         {
  895.             pointsX.push_back(p.x);
  896.             pointsY.push_back(p.y);
  897.         }
  898.  
  899.         pair<vector<float>, vector<float>> controlPointsX = computeControlPoints(pointsX), controlPointsY = computeControlPoints(pointsY);
  900.         bezierPoints = computeBezierPoints(pointsX, pointsY, controlPointsX, controlPointsY);
  901.  
  902.         createModelLine();
  903.     }
  904.     if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
  905.     {
  906.         if (points.size() < 2)
  907.             return;
  908.         drawing3DModel = true;
  909.         if (points.size() == 2)
  910.         {
  911.             float a = bezierPoints[0].y - bezierPoints[1].y;
  912.             float b = bezierPoints[1].x - bezierPoints[0].x;
  913.             normals.push_back(point(a, b));
  914.             normals.push_back(point(a, b));
  915.             create3DModel();
  916.             return;
  917.         }
  918.         normals.push_back(point(bezierPoints[0].y - bezierPoints[2].y, bezierPoints[2].x - bezierPoints[0].x));
  919.         for (int i = 0; i < bezierPoints.size() - 2; i++)
  920.         {
  921.             float a = bezierPoints[i].y - bezierPoints[i + 2].y;
  922.             float b = bezierPoints[i + 2].x - bezierPoints[i].x;
  923.             normals.push_back(point(a, b));
  924.         }
  925.         normals.push_back(normals[normals.size() - 1]);
  926.         create3DModel();
  927.         return;
  928.     }
  929. }
  930.  
  931. void mouse_callback(GLFWwindow* window, double xpos, double ypos)
  932. {
  933.     //cout << xpos << "  " <<ypos << endl;
  934.     //mvp = matrix::rotate(mvp, radians(xpos / 4.5), v3(1.0, 0.0, 0.0));
  935.     //mvp = matrix::rotate(mvp, radians(ypos / 4.5), v3(0.0, 1.0, 0.0));
  936. }
  937.  
  938. int main()
  939. {
  940.     // Initialize OpenGL
  941.     if (!initOpenGL())
  942.         return -1;
  943.  
  944.     // Initialize graphical resources.
  945.     bool isOk = init();
  946.  
  947.     glfwSetCursorPosCallback(g_window, mouse_callback);
  948.     glfwSetMouseButtonCallback(g_window, mouse_button_callback);
  949.  
  950.  
  951.     if (isOk)
  952.     {
  953.         // Main loop until window closed or escape pressed.
  954.         int ax = 0, ay = 0, az = 0, ez = 1, ey = 1, ly = 0, lz = 0;
  955.         while (glfwGetKey(g_window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(g_window) == 0)
  956.         {
  957. #pragma region обработка кнопок
  958.             if (glfwGetKey(g_window, GLFW_KEY_UP) == GLFW_PRESS) {
  959.                 ax--;
  960.             }
  961.             if (glfwGetKey(g_window, GLFW_KEY_DOWN) == GLFW_PRESS) {
  962.                 ax++;
  963.             }
  964.             if (glfwGetKey(g_window, GLFW_KEY_LEFT) == GLFW_PRESS) {
  965.                 ay++;
  966.             }
  967.             if (glfwGetKey(g_window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
  968.                 ay--;
  969.             }
  970.             if (glfwGetKey(g_window, GLFW_KEY_KP_8) == GLFW_PRESS) {
  971.                 ey++;
  972.             }
  973.             if (glfwGetKey(g_window, GLFW_KEY_KP_2) == GLFW_PRESS) {
  974.                 ey--;
  975.             }
  976.             if (glfwGetKey(g_window, GLFW_KEY_KP_6) == GLFW_PRESS) {
  977.                 ez++;
  978.             }
  979.             if (glfwGetKey(g_window, GLFW_KEY_KP_4) == GLFW_PRESS) {
  980.                 ez--;
  981.             }
  982.             if (glfwGetKey(g_window, GLFW_KEY_W) == GLFW_PRESS) {
  983.                 ly++;
  984.             }
  985.             if (glfwGetKey(g_window, GLFW_KEY_S) == GLFW_PRESS) {
  986.                 ly--;
  987.             }
  988.             if (glfwGetKey(g_window, GLFW_KEY_D) == GLFW_PRESS) {
  989.                 lz++;
  990.             }
  991.             if (glfwGetKey(g_window, GLFW_KEY_A) == GLFW_PRESS) {
  992.                 lz--;
  993.             }
  994. #pragma endregion
  995.  
  996.             for (int i = 0; i < coordClick.size(); i++)
  997.                 cout << coordClick[i].first << " " << coordClick[i].second << endl;
  998.  
  999.             // Draw scene.
  1000.             draw(ax, ay, az, ey, ez, ly, lz);
  1001.  
  1002.             // Swap buffers.
  1003.             glfwSwapBuffers(g_window);
  1004.             // Poll window events.
  1005.             glfwPollEvents();
  1006.  
  1007.             Sleep(20);
  1008.         }
  1009.     }
  1010.  
  1011.     // Cleanup graphical resources.
  1012.     cleanup();
  1013.  
  1014.     // Tear down OpenGL.
  1015.     tearDownOpenGL();
  1016.  
  1017.     return isOk ? 0 : -1;
  1018. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement