#include <glut.h>
#include <iostream>
#include <vector>
#include <algorithm>
struct Point {
int x, y;
Point(int _x, int _y) : x(_x), y(_y) {}
};
std::vector<Point> matrixMultiply(const std::vector<Point>& points, const std::vector<std::vector<float>>& matrix) {
std::vector<Point> transformedPoints;
for (const auto& p : points) {
float newX = matrix[0][0] * p.x + matrix[0][1] * p.y + matrix[0][2];
float newY = matrix[1][0] * p.x + matrix[1][1] * p.y + matrix[1][2];
transformedPoints.emplace_back(static_cast<int>(newX), static_cast<int>(newY));
}
return transformedPoints;
}
std::vector<std::vector<float>> rotationMatrix(float angle) {
float rad = angle * 3.1415926 / 180.0;
return {
{std::cos(rad), -std::sin(rad), 0},
{std::sin(rad), std::cos(rad), 0},
{0, 0, 1}
};
}
std::vector<std::vector<float>> scalingMatrix(float sx, float sy) {
return {
{sx, 0, 0},
{0, sy, 0},
{0, 0, 1}
};
}
std::vector<std::vector<float>> translationMatrix(float tx, float ty) {
return {
{1, 0, tx},
{0, 1, ty},
{0, 0, 1}
};
}
void midPointLine(int x1, int y1, int x2, int y2, std::vector<Point>& points) {
int dx = std::abs(x2 - x1);
int dy = std::abs(y2 - y1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
while (true) {
points.emplace_back(x1, y1);
if (x1 == x2 && y1 == y2) break;
int e2 = 2 * err;
if (e2 > -dy) { err -= dy; x1 += sx; }
if (e2 < dx) { err += dx; y1 += sy; }
}
}
void drawLine(int x1, int y1, int x2, int y2, std::vector<Point>& points) {
midPointLine(x1, y1, x2, y2, points);
}
void fillPolygon(const std::vector<Point>& polygon, std::vector<Point>& filledPoints) {
int minY = polygon[0].y, maxY = polygon[0].y;
for (const auto& p : polygon) {
minY = std::min(minY, p.y);
maxY = std::max(maxY, p.y);
}
for (int y = minY; y <= maxY; y++) {
std::vector<int> intersections;
for (size_t i = 0; i < polygon.size(); i++) {
const auto& p1 = polygon[i];
const auto& p2 = polygon[(i + 1) % polygon.size()];
if ((p1.y <= y && p2.y > y) || (p2.y <= y && p1.y > y)) {
int x = p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y);
intersections.push_back(x);
}
}
std::sort(intersections.begin(), intersections.end());
for (size_t i = 0; i < intersections.size(); i += 2) {
for (int x = intersections[i]; x < intersections[i + 1]; x++) {
filledPoints.emplace_back(x, y);
}
}
}
}
std::vector<Point> threeDotsVertices[] = {
{{60, 360}, {80, 390}, {100, 350}},
{{70, 290}, {95, 320}, {110, 280}},
{{85, 220}, {110, 250}, {125, 210}}
};
std::vector<Point> leftStrokeVertices = {
{180, 420}, {210, 430},
{185, 380}, {155, 370}
};
std::vector<Point> upperHorizontalVertices = {
{220, 420}, {360, 420},
{360, 400}, {220, 400}
};
std::vector<Point> lowerHorizontalVertices = {
{210, 330}, {370, 330},
{370, 310}, {210, 310}
};
std::vector<Point> verticalLineVertices = {
{290, 450}, {310, 450},
{310, 310}, {290, 310}
};
std::vector<Point> mouthOuterVertices = {
{220, 270}, {360, 270},
{340, 190}, {240, 190}
};
std::vector<Point> mouthInnerVertices = {
{250, 250}, {330, 250},
{315, 205}, {265, 205}
};
void drawOutlines(const std::vector<Point>& vertices, std::vector<Point>& outlinePoints) {
for (size_t i = 0; i < vertices.size(); i++) {
drawLine(vertices[i].x, vertices[i].y, vertices[(i + 1) % vertices.size()].x, vertices[(i + 1) % vertices.size()].y, outlinePoints);
}
}
void fillAllParts(const std::vector<Point>& vertices, std::vector<Point>& filledPoints) {
fillPolygon(vertices, filledPoints);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
int minX = 9999, minY = 9999, maxX = 0, maxY = 0;
std::vector<std::vector<Point>> allVertices = {
threeDotsVertices[0], threeDotsVertices[1], threeDotsVertices[2],
leftStrokeVertices, upperHorizontalVertices, lowerHorizontalVertices,
verticalLineVertices, mouthOuterVertices, mouthInnerVertices
};
for (const auto& vertices : allVertices) {
for (const auto& p : vertices) {
minX = std::min(minX, p.x);
minY = std::min(minY, p.y);
maxX = std::max(maxX, p.x);
maxY = std::max(maxY, p.y);
}
}
int centerX = (minX + maxX) / 2;
int centerY = (minY + maxY) / 2;
glViewport(0, 0, 900, 600);
auto translateToCenter = translationMatrix(-centerX, -centerY);
auto rotMatrix = rotationMatrix(45);
auto translateBack = translationMatrix(centerX + 50, centerY);
std::vector<std::vector<float>> combinedMatrix = {
{translateBack[0][0] * (rotMatrix[0][0] * translateToCenter[0][0] + rotMatrix[0][1] * translateToCenter[1][0]) + translateBack[0][1] * (rotMatrix[1][0] * translateToCenter[0][0] + rotMatrix[1][1] * translateToCenter[1][0]),
translateBack[0][0] * (rotMatrix[0][0] * translateToCenter[0][1] + rotMatrix[0][1] * translateToCenter[1][1]) + translateBack[0][1] * (rotMatrix[1][0] * translateToCenter[0][1] + rotMatrix[1][1] * translateToCenter[1][1]),
translateBack[0][0] * (rotMatrix[0][0] * translateToCenter[0][2] + rotMatrix[0][1] * translateToCenter[1][2] + rotMatrix[0][2]) + translateBack[0][1] * (rotMatrix[1][0] * translateToCenter[0][2] + rotMatrix[1][1] * translateToCenter[1][2] + rotMatrix[1][2]) + translateBack[0][2]},
{translateBack[1][0] * (rotMatrix[0][0] * translateToCenter[0][0] + rotMatrix[0][1] * translateToCenter[1][0]) + translateBack[1][1] * (rotMatrix[1][0] * translateToCenter[0][0] + rotMatrix[1][1] * translateToCenter[1][0]),
translateBack[1][0] * (rotMatrix[0][0] * translateToCenter[0][1] + rotMatrix[0][1] * translateToCenter[1][1]) + translateBack[1][1] * (rotMatrix[1][0] * translateToCenter[0][1] + rotMatrix[1][1] * translateToCenter[1][1]),
translateBack[1][0] * (rotMatrix[0][0] * translateToCenter[0][2] + rotMatrix[0][1] * translateToCenter[1][2] + rotMatrix[0][2]) + translateBack[1][1] * (rotMatrix[1][0] * translateToCenter[0][2] + rotMatrix[1][1] * translateToCenter[1][2] + rotMatrix[1][2]) + translateBack[1][2]},
{0, 0, 1}
};
std::vector<Point> outlinePoints1;
std::vector<Point> filledPoints1;
for (const auto& vertices : allVertices) {
auto transformedVertices = matrixMultiply(vertices, combinedMatrix);
drawOutlines(transformedVertices, outlinePoints1);
fillAllParts(transformedVertices, filledPoints1);
}
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (const auto& p : outlinePoints1) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_POINTS);
for (const auto& p : filledPoints1) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(1.0, 0.0, 0.0);
std::vector<Point> innerMouthFill1;
auto transformedInnerMouth = matrixMultiply(mouthInnerVertices, combinedMatrix);
fillPolygon(transformedInnerMouth, innerMouthFill1);
glBegin(GL_POINTS);
for (const auto& p : innerMouthFill1) {
glVertex2i(p.x, p.y);
}
glEnd();
glViewport(300, 0, 300, 600);
auto scaleMatrix = scalingMatrix(0.5, 0.5);
std::vector<Point> outlinePoints2;
std::vector<Point> filledPoints2;
for (const auto& vertices : allVertices) {
auto transformedVertices = matrixMultiply(vertices, scaleMatrix);
drawOutlines(transformedVertices, outlinePoints2);
fillAllParts(transformedVertices, filledPoints2);
}
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (const auto& p : outlinePoints2) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_POINTS);
for (const auto& p : filledPoints2) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(1.0, 0.0, 0.0);
std::vector<Point> innerMouthFill2;
auto transformedInnerMouth2 = matrixMultiply(mouthInnerVertices, scaleMatrix);
fillPolygon(transformedInnerMouth2, innerMouthFill2);
glBegin(GL_POINTS);
for (const auto& p : innerMouthFill2) {
glVertex2i(p.x, p.y);
}
glEnd();
glViewport(600, 0, 300, 600);
auto transMatrix3 = translationMatrix(100, 50);
std::vector<Point> outlinePoints3;
std::vector<Point> filledPoints3;
for (const auto& vertices : allVertices) {
auto transformedVertices = matrixMultiply(vertices, transMatrix3);
drawOutlines(transformedVertices, outlinePoints3);
fillAllParts(transformedVertices, filledPoints3);
}
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (const auto& p : outlinePoints3) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_POINTS);
for (const auto& p : filledPoints3) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(1.0, 0.0, 0.0);
std::vector<Point> innerMouthFill3;
auto transformedInnerMouth3 = matrixMultiply(mouthInnerVertices, transMatrix3);
fillPolygon(transformedInnerMouth3, innerMouthFill3);
glBegin(GL_POINTS);
for (const auto& p : innerMouthFill3) {
glVertex2i(p.x, p.y);
}
glEnd();
glFlush();
}
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
gluOrtho2D(0, 900, 0, 600);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(900, 600);
glutCreateWindow("Hollow and Filled Hao");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}