#include "stdafx.h"
#include <iostream>
#include <vector>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <math.h>
#include <Windows.h>
using namespace std;
#define Width 600
#define Height 640
typedef struct Point
{
GLint x, y;
} Point;
typedef struct Edge
{
vector<Point> p;
} Edge;
typedef struct RGB_type
{
float red, green, blue;
} RGB_type;
RGB_type pixels[Width*Height];
vector<Point> points;
vector<Edge> edges;
GLFWwindow* window;
bool running = true;
int mouseX, mouseY;
int oldMouseX = -1, oldMouseY = -1;
int FirstMouseX = -1, FirstMouseY = -1;
int oldY = 0, firstY1;
bool last = false;
int GetIndex(int x, int y)
{
return (x + (Height - y)*Width);
}
void SetPixel(int x, int y, int c)
{
int ind = GetIndex(x, y);
pixels[ind].red = c;
pixels[ind].blue = c;
pixels[ind].green = c;
}
void Fill()
{
for (int i = 0; i < Height - 1; i++)
{
bool flag = false;
for (int j = 1; j < Width - 1; j++)
{
if (pixels[GetIndex(j, i)].blue == 1)
flag = !flag;
flag ? SetPixel(j, i, 1) : SetPixel(j, i, 0);
}
}
}
void DrawLine(int x0, int y0, int x1, int y1)
{
if (oldY == 0)
firstY1 = y1;
int x = x0;
int y = y0;
int lastY;
if ((y0 - oldY) * (y1 - y0) < 0)
SetPixel(x + 1, y, 1);
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
int signX = (x0 < x1) ? 1 : -1;
int signY = (y0 < y1) ? 1 : -1;
int e2 = 2 * dx - dy;
SetPixel(x, y, 1);
for (int i = 0; i < dy - 1 + last; i++)
{
lastY = y;
while (e2 >= 0)
{
x += signX;
e2 -= 2 * dy;
}
y += signY;
e2 += 2 * dx;
if (pixels[GetIndex(x, y)].blue == 1)
SetPixel(x + 1, y, 1);
SetPixel(x, y, 1);
}
oldY = y0;
}
void PostFilter()
{
RGB_type *pNew = nullptr;
pNew = new RGB_type[Width*Height];
double errR, errG, errB;
for (int y = 1; y < Height - 1; y++)
for (int x = 1; x < Width - 1; x++)
{
errR = errG = errB = 0;
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
errR += pixels[GetIndex(j + x, i + y)].red;
errG += pixels[GetIndex(j + x, i + y)].green;
errB += pixels[GetIndex(j + x, i + y)].blue;
}
}
errR /= 9; errB /= 9; errG /= 9;
pNew[GetIndex(x, y)].red = errR;
pNew[GetIndex(x, y)].green = errG;
pNew[GetIndex(x, y)].blue = errB;
}
for (int i = 0; i < Width*Height - 1; i++)
{
pixels[i].blue = pNew[i].blue;
pixels[i].red = pNew[i].red;
pixels[i].green = pNew[i].green;
}
delete[]pNew;
}
void Clear()
{
for (int i = 0; i < Width*Height; i++)
pixels[i] = { 0, 0, 0 };
oldMouseX = -1; oldMouseY = -1;
FirstMouseX = -1; FirstMouseY = -1;
last = 0;
}
static void keyboard_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
running = false;
if (key == GLFW_KEY_D && action == GLFW_PRESS)
Fill();
if (key == GLFW_KEY_S && action == GLFW_PRESS)
PostFilter();
if (key == GLFW_KEY_E && action == GLFW_PRESS)
{
last = true;
DrawLine(oldMouseX, oldMouseY, FirstMouseX, FirstMouseY);
}
if (key == GLFW_KEY_C && action == GLFW_PRESS)
Clear();
}
static void mouse_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && oldMouseX != mouseX && oldMouseY != mouseY)
{
if (FirstMouseX == -1)
{
FirstMouseX = mouseX;
FirstMouseY = mouseY;
}
SetPixel(mouseX, mouseY, 1);
if (oldMouseX != -1)
{
DrawLine(oldMouseX, oldMouseY, mouseX, mouseY);
}
oldMouseX = mouseX;
oldMouseY = mouseY;
}
if (button == GLFW_MOUSE_BUTTON_RIGHT)
{
}
}
static void cursor_callback(GLFWwindow* window, double x, double y)
{
mouseX = x;
mouseY = y;
}
int main()
{
if (!glfwInit())
{
cerr << "error in GLFW";
return -1;
}
window = glfwCreateWindow(Width, Height, "GL", NULL, NULL);
if (window == NULL){
cerr << "Невозможно открыть окно GLFW. Если у вас Intel GPU, то он не поддерживает версию 3.3\n";
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK) {
cerr << "Невозможно инициализировать GLEW\n";
return -1;
}
for (int i = 0; i < Width; i++)
{
for (int j = 0; j < Height; j++)
{
SetPixel(i, Height - j, 0);
}
}
glEnable(GL_DEPTH_TEST);
glfwSetKeyCallback(window, keyboard_callback);
glfwSetMouseButtonCallback(window, mouse_callback);
glfwSetCursorPosCallback(window, cursor_callback);
while (running)
{
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glMatrixMode(GL_PROJECTION);
glClearColor(0.0f, 0.0f, 0.25f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
glDrawPixels(Width, Height, GL_RGB, GL_FLOAT, pixels);
glfwSwapBuffers(window);
glfwPollEvents();
}
return 0;
}