//
// main.cpp
// GLFW Lab 3.1
//
// Created by Кирилл Снегур on 19.03.2019.
// Copyright © 2019 ALLMIGHT DEVELOPMENT. All rights reserved.
//
//
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <math.h>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
//const GLchar* vertexShaderSource = "#version 330 core\n"
//"layout (location = 0) in vec3 position;\n"
//"void main()\n"
//"{\n"
//"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
//"}\0";
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"uniform mat4 matrix;"
//"in vec3 pos;"
"void main()\n"
"{\n"
"gl_Position = matrix * vec4( position, 1.0);\n"
//"gl_Position = matrix * vec4(x, y, z, 1.0);\n"
// "gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
typedef struct {
float x, y, z;
} Point;
vector<Point> vertices;
vector<unsigned int> indices;
int vertCount;
GLuint VAO, VBO, EBO;
//GLfloat *vertices;
int WIDTH = 800, HEIGHT = 800;
float x = 0, y = 0, z = 0;
float RotateX = 0.0f, RotateY = 0.0f, RotateZ = 0.0f;
float PositionX = 1.0f, PositionY = 1.0f, PositionZ = 1.0f;
int circleValue = 30, triangleValue =20;
GLfloat PologonModeValue = GL_LINE;
GLfloat phi = asin(0.25 / sqrt(2.0));
GLfloat teta = asin(0.25 / sqrt(2.0 - 0.25 * 0.25));
GLfloat TransformationMatrix[4][4] = {
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
};
static double PI = 3.1415926535897932384626433832795;
glm::mat4 project;
glm::mat4 model = glm::translate(glm::mat4(1.f), { x, y, z });
GLuint shaderProgram;
void framebuffer_size_callback(GLFWwindow* window, int width, int height){
if(width>height)
{
glViewport((width-height)/2, 0, std::min(width,height), std::min(width,height));
}
else
glViewport(0, (height-width)/2, std::min(width,height), std::min(width,height));
};
void keyCallback(GLFWwindow * window, int key, int scancode, int action, int mode) {
GLfloat step = 0.05f;
GLfloat rotateStep = 5.0f;
GLfloat valueStep = 1.0f;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
switch (key) {
case GLFW_KEY_D:
RotateX -= rotateStep;
break;
case GLFW_KEY_A:
RotateX += rotateStep;
break;
case GLFW_KEY_S:
RotateY -= rotateStep;
break;
case GLFW_KEY_W:
RotateY += rotateStep;
break;
case GLFW_KEY_Q:
RotateZ += rotateStep;
break;
case GLFW_KEY_E:
RotateZ -= rotateStep;
break;
case GLFW_KEY_LEFT:
x -= step;
break;
case GLFW_KEY_RIGHT:
x += step;
break;
case GLFW_KEY_UP:
y += step;
break;
case GLFW_KEY_DOWN:
y -= step;
break;
case GLFW_KEY_C:
circleValue -= valueStep;
break;
case GLFW_KEY_V:
circleValue += valueStep;
break;
case GLFW_KEY_R:
triangleValue -= valueStep;
break;
case GLFW_KEY_F:
triangleValue += valueStep;
break;
case GLFW_KEY_1:
PologonModeValue = GL_FILL;
break;
case GLFW_KEY_2:
PologonModeValue = GL_LINE;
}
}
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset){
PositionX += 0.5 * yoffset;
PositionY += 0.5 * yoffset;
PositionZ += 0.5 * yoffset;
}
void Draw_Cube(GLfloat size){
glBegin(GL_QUADS);
glVertex3f( -size / 2, -size / 2, -size / 2);
glVertex3f( -size / 2, size / 2, -size / 2);
glVertex3f( -size / 2, size / 2, size / 2);
glVertex3f( -size / 2, -size / 2, size / 2);
glVertex3f( size / 2, -size / 2, -size / 2);
glVertex3f( size / 2, -size / 2, size / 2);
glVertex3f( size / 2, size / 2, size / 2);
glVertex3f( size / 2, size / 2, -size / 2);
glVertex3f( -size / 2, -size / 2, -size / 2);
glVertex3f( -size / 2, -size / 2, size / 2);
glVertex3f( size / 2, -size / 2, size / 2);
glVertex3f( size / 2, -size / 2, -size / 2);
glVertex3f( -size / 2, size / 2, -size / 2);
glVertex3f( -size / 2, size / 2, size / 2);
glVertex3f( size / 2, size / 2, size / 2);
glVertex3f( size / 2, size / 2, -size / 2);
glVertex3f( -size / 2, -size / 2, -size / 2);
glVertex3f( size / 2, -size / 2, -size / 2);
glVertex3f( size / 2, size / 2, -size / 2);
glVertex3f( -size / 2, size / 2, -size / 2);
glVertex3f( -size / 2, -size / 2, size / 2);
glVertex3f( size / 2, -size / 2, size / 2);
glVertex3f( size / 2, size / 2, size / 2);
glVertex3f( -size / 2, size / 2, size / 2);
glEnd();
}
void Draw_Tor(int roundValue, int shapesValue, float externalRadDelta, float interiorRadDelta) {
glPolygonMode(GL_FRONT_AND_BACK, PologonModeValue);
double externalRad = 2.0 * PI / roundValue;
double interiorRad = 2.0 * PI / shapesValue;
vertices.resize(2*(roundValue * (shapesValue + 1) + 1));
indices.clear();
vertCount = 0;
for (int i = 0; i < roundValue; i++) {
double stepOne = i * externalRad;
double stepTwo = stepOne + externalRad;
GLdouble HorizontalStepOne = cos(stepOne);
GLdouble VerticalStepOne = sin(stepOne);
GLdouble HorizontalStepTwo = cos(stepTwo);
GLdouble VerticalStepTwo = sin(stepTwo);
//glBegin(GL_TRIANGLE_STRIP);
for (int j = 0; j <= shapesValue; j++) {
double b = j * interiorRad;
GLdouble externalRadValue = interiorRadDelta * cos(b) + externalRadDelta;
GLdouble interiorRadValue = interiorRadDelta * sin(b);
vertices[vertCount].x = HorizontalStepTwo * externalRadValue;
vertices[vertCount].y = VerticalStepTwo * externalRadValue;
vertices[vertCount].z = interiorRadValue;
indices.push_back(vertCount++);
vertices[vertCount].x = HorizontalStepOne * externalRadValue;
vertices[vertCount].y = VerticalStepOne * externalRadValue;
vertices[vertCount].z = interiorRadValue;
indices.push_back(vertCount++);
}
}
// glBindVertexArray(VAO);
//
// glBindBuffer(GL_ARRAY_BUFFER, VBO);
// glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Point), &vertices[0], GL_DYNAMIC_DRAW);
//
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_DYNAMIC_DRAW);
//
// GLuint posAttr = glGetAttribLocation(shaderProgram, "pos");;
// glVertexAttribPointer(posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(Point), (GLvoid*)(0*sizeof(GLfloat)));
// glEnableVertexAttribArray(posAttr);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Point), &vertices[0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Point), (GLvoid*)(0*sizeof(GLfloat)));
glEnableVertexAttribArray(0);
}
void Draw_dimetrialProection() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(-phi*(180/3.14) , 1.0, 0.0, 0.0);
glRotatef(-teta*(180/3.14) , 0.0, 1.0, 0.0);
glTranslatef(-0.9, -0.7, -0.5);
glScaled(0.2, 0.2, 0.2);
Draw_Cube(1);
}
int main(void) {
if (!glfwInit()) {
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Lab8", NULL, NULL);
glfwMakeContextCurrent(window);
//
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, keyCallback);
glfwSetScrollCallback(window, scroll_callback);
glewExperimental = GL_TRUE;
glewInit();
glEnable(GL_DEPTH_TEST);
GLfloat teta = (float)M_PI * 30 / 180;
GLfloat matrix[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
-cosf(teta), -sinf(teta), -1, 0,
0, 0, 0, 1
};
project = glm::make_mat4x4(matrix);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwPollEvents();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf(*TransformationMatrix);
Draw_Tor(circleValue,triangleValue, 0.2f , 0.1f);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glMatrixMode(GL_MODELVIEW);
glm::mat4 model = glm::translate(glm::mat4(1.f), { x, y, z });
model *= glm::rotate(model, glm::radians(RotateX), {1, 0, 0});
model *= glm::rotate(model, glm::radians(RotateY), {0, 1, 0});
model *= glm::rotate(model, glm::radians(RotateZ), {0, 0, 1});
model = glm::scale(model, {PositionX, PositionY, PositionZ});
glPolygonMode(GL_FRONT_AND_BACK, PologonModeValue);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "matrix"), 1, GL_FALSE, glm::value_ptr(project * model));
glDrawElements(GL_TRIANGLE_STRIP, 2* circleValue * (triangleValue + 1), GL_UNSIGNED_INT, 0);
glLoadIdentity();
glBindVertexArray(0);
Draw_dimetrialProection();
Draw_Tor(circleValue,triangleValue, 0.2f , 0.1f);
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwDestroyWindow(window);
glfwTerminate();
}