diff --git a/src/main.cpp b/src/main.cpp index 38751f0..99a445c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,4 @@ +#pragma execution_character_set("utf-8") #include #include #include "check_gl.hpp" // includes glad/glad.h @@ -7,41 +8,294 @@ #include #include -static void render() { +constexpr float pi = 3.1415926535897f; +glm::vec3 rotate(glm::vec3 p, glm::vec3 c, int angle) { + glm::vec3 afterPoint; + float sita = float(angle) / 360.0f * 2.0f * pi; + afterPoint.x = cosf(sita) * (p.x - c.x) - sinf(sita) * (p.y - c.y) + c.x; + afterPoint.y = sinf(sita) * (p.x - c.x) + cosf(sita) * (p.y - c.y) + c.y; + afterPoint.z = 0.0f; + return afterPoint; +} +bool dotUpdateLock = false; +bool lockLock = false; + +int x[] = { int(210 / 2) - 1,int(90 / 2) - 1,int(330 / 2) - 1 }; + +void donut(float o_x, float o_y, int startAngle, int endAngle, int num) { //o_x代表一个圆的中心x坐标,下面的点加上o_x为移动后的坐标 + //////……这里加上int startAngle,int endAngle glBegin(GL_TRIANGLES); - glColor3f(1.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 0.5f, 0.0f); - glColor3f(0.0f, 1.0f, 0.0f); - glVertex3f(-0.5f, -0.5f, 0.0f); - glColor3f(0.0f, 0.0f, 1.0f); - glVertex3f(0.5f, -0.5f, 0.0f); + constexpr int n = 180; + float radius = 0.45f; + float inner_radius = 0.225f; + + o_x = o_x / 2.0f + 0.5f; + o_y = (-1.0f) * o_y / 2.0f + 0.5f;//要把圆心的坐标 转化为 坐标系原点在左上角的坐标 + + o_x = 3.0f * o_x / 4.0f; + o_y = 3.0f * o_y / 4.0f;//计算完缩小多少倍后 + radius = 3.0f * radius / 4.0f; + inner_radius = 3.0f * inner_radius / 4.0f; //R(外圈圆半径)和r(内圈圆半径)要乘以缩小的倍数 + + o_x = (o_x - 0.5f) * 2.0f; + o_y = (o_y - 0.5f) * (-2.0f);//再转化为坐标系原点屏幕中心的坐标。 + + if (!((x[num] % 180 > startAngle) && (x[num] > 180))) //因为要让它超过startAngle且跑过一圈就不++了 + x[num]++; + else { + if (lockLock == false) { + dotUpdateLock = true; + lockLock = true; + } + } + + + if (num == 0) { //加上颜色 + glColor3f(1.0f, 0.0f, 0.0f); + } + else if (num == 1) { + glColor3f(0.0f, 1.0f, 0.0f); + } + else { + glColor3f(0.0f, 0.0f, 1.0f); + } + //std::cout << "DI" << num << "GE" << " : x=" << o_x << " ;y=" << o_y << std::endl; + for (int i = endAngle; i < x[num]; i++) { + //if (o_x - 0.5f <= 0.00001f) std::cout << "i: " << i << std::endl; + if (i % 180 < startAngle || i % 180 >= endAngle) { + float angle = i / (float)n * pi * 2; + float angle_next = (i + 1) / (float)n * pi * 2; + glVertex3f(radius * sinf(angle) + o_x, radius * cosf(angle) + o_y, 0.0f); + glVertex3f(radius * sinf(angle_next) + o_x, radius * cosf(angle_next) + o_y, 0.0f); + glVertex3f(inner_radius * sinf(angle) + o_x, inner_radius * cosf(angle) + o_y, 0.0f); + + glVertex3f(inner_radius * sinf(angle_next) + o_x, inner_radius * cosf(angle_next) + o_y, 0.0f); + glVertex3f(inner_radius * sinf(angle) + o_x, inner_radius * cosf(angle) + o_y, 0.0f); + glVertex3f(radius * sinf(angle_next) + o_x, radius * cosf(angle_next) + o_y, 0.0f); + } + } CHECK_GL(glEnd()); - /* glBegin(GL_TRIANGLES); */ - /* constexpr int n = 100; */ - /* constexpr float pi = 3.1415926535897f; */ - /* float radius = 0.5f; */ - /* float inner_radius = 0.25f; */ - /* static int x = 0; */ - /* x++; */ - /* if (x > n) */ - /* x -= n; */ - /* for (int i = 0; i < x; i++) { */ - /* float angle = i / (float)n * pi * 2; */ - /* float angle_next = (i + 1) / (float)n * pi * 2; */ - /* glVertex3f(0.0f, 0.0f, 0.0f); */ - /* glVertex3f(radius * sinf(angle), radius * cosf(angle), 0.0f); */ - /* glVertex3f(radius * sinf(angle_next), radius * cosf(angle_next), 0.0f); */ - /* glVertex3f(inner_radius * sinf(angle), inner_radius * cosf(angle), 0.0f); */ - /* glVertex3f(inner_radius * sinf(angle_next), inner_radius * cosf(angle_next), 0.0f); */ - /* glVertex3f(inner_radius * sinf(angle), inner_radius * cosf(angle), 0.0f); */ - /* glVertex3f(radius * sinf(angle_next), radius * cosf(angle_next), 0.0f); */ - /* } */ - /* CHECK_GL(glEnd()); */ +} + +void donut_two(float o_x, float o_y, int startAngle, int endAngle, int num, int blueRotateAngle) { //o_x代表一个圆的中心x坐标,下面的点加上o_x为移动后的坐标 + //////……这里加上int startAngle,int endAngle + glBegin(GL_TRIANGLES); + constexpr int n = 180;//////……这里变成360,因为方便计算角度 + constexpr float pi = 3.1415926535897f; + float radius = 0.45f; + float inner_radius = 0.225f; + + o_x = o_x / 2.0f + 0.5f; + o_y = (-1.0f) * o_y / 2.0f + 0.5f;//要把圆心的坐标 转化为 坐标系原点在左上角的坐标 + + o_x = 3.0f * o_x / 4.0f; + o_y = 3.0f * o_y / 4.0f;//计算完缩小多少倍后 + radius = 3.0f * radius / 4.0f; + inner_radius = 3.0f * inner_radius / 4.0f; //R(外圈圆半径)和r(内圈圆半径)要乘以缩小的倍数 + + o_x = (o_x - 0.5f) * 2.0f; + o_y = (o_y - 0.5f) * (-2.0f);//再转化为坐标系原点屏幕中心的坐标。 + + if (num == 0) { //加上颜色 + glColor3f(1.0f, 0.0f, 0.0f); + } + else if (num == 1) { + glColor3f(0.0f, 1.0f, 0.0f); + } + else { + glColor3f(0.0f, 0.0f, 1.0f); + } + + for (int i = -15 + blueRotateAngle; i < n; i++) { + if (i >= 0 && (i < startAngle || i >= endAngle)) {//////……这里变成这样,仔细想一下上图紫色的线 + float angle = i / (float)n * pi * 2; + float angle_next = (i + 1) / (float)n * pi * 2; + glVertex3f(radius * sinf(angle) + o_x, radius * cosf(angle) + o_y, 0.0f); + glVertex3f(radius * sinf(angle_next) + o_x, radius * cosf(angle_next) + o_y, 0.0f); + glVertex3f(inner_radius * sinf(angle) + o_x, inner_radius * cosf(angle) + o_y, 0.0f); + + glVertex3f(inner_radius * sinf(angle_next) + o_x, inner_radius * cosf(angle_next) + o_y, 0.0f); + glVertex3f(inner_radius * sinf(angle) + o_x, inner_radius * cosf(angle) + o_y, 0.0f); + glVertex3f(radius * sinf(angle_next) + o_x, radius * cosf(angle_next) + o_y, 0.0f); + } + } + CHECK_GL(glEnd()); +} + + +void fangfang(glm::vec3 vertices[]) { + glBegin(GL_POLYGON); + glColor3f(16.0f / 255.0f, 53.0f / 255.0f, 86.0f / 255.0f); + glVertex3f(vertices[0].x, vertices[0].y, vertices[0].z); + glColor3f(16.0f / 255.0f, 53.0f / 255.0f, 86.0f / 255.0f); + glVertex3f(vertices[1].x, vertices[1].y, vertices[1].z); + glColor3f(160.0f / 255.0f, 185.0f / 255.0f, 208.0f / 255.0f); + glVertex3f(vertices[2].x, vertices[2].y, vertices[2].z); + glColor3f(160.0f / 255.0f, 185.0f / 255.0f, 208.0f / 255.0f); + glVertex3f(vertices[3].x, vertices[3].y, vertices[3].z); + CHECK_GL(glEnd()); +} + + + +glm::vec3 O = glm::vec3(-0.25f, 0.625f, 0.0f); +float length = 0.04f; +glm::vec3 a = glm::vec3(O.x - length, O.y, 0.0f); +glm::vec3 b = glm::vec3(O.x - length, O.y - 2 * length, 0.0f); +glm::vec3 c = glm::vec3(O.x, O.y - 2 * length, 0.0f); +glm::vec3 d = glm::vec3(O.x + length, O.y - 2 * length, 0.0f); +glm::vec3 e = glm::vec3(O.x + length, O.y, 0.0f); + +glm::vec3 f = glm::vec3(O.x - length, O.y - 3 * length, 0.0f); +glm::vec3 g = glm::vec3(O.x + length, O.y - 3 * length, 0.0f); + + +void dotUpdate(int rotateAngle) { //让其旋转多少度 + a = rotate(a, O, rotateAngle); + b = rotate(b, O, rotateAngle); + c = rotate(c, O, rotateAngle); + d = rotate(d, O, rotateAngle); + e = rotate(e, O, rotateAngle); + f = rotate(f, O, rotateAngle); + g = rotate(g, O, rotateAngle); +} + +void dotHuiQu() { //和O.x的新位置保持更新 + a = glm::vec3(O.x - length, O.y, 0.0f); + b = glm::vec3(O.x - length, O.y - 2 * length, 0.0f); + c = glm::vec3(O.x, O.y - 2 * length, 0.0f); + d = glm::vec3(O.x + length, O.y - 2 * length, 0.0f); + e = glm::vec3(O.x + length, O.y, 0.0f); + + f = glm::vec3(O.x - length, O.y - 3 * length, 0.0f); + g = glm::vec3(O.x + length, O.y - 3 * length, 0.0f); +} + +void bresenham(int x0, int y0, int x1, int y1) { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = (dx > dy ? dx : -dy) / 2; + + for (int i = 0; i < 4; i++) { //速度快一点 + if (x0 != x1 || y0 != y1) { + int e2 = err; + if (e2 > -dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } + else { + dotUpdateLock = true; + } + } + O.x = float(x0) / 640.0f; O.y = float(y0) / 640.0f; + //std::cout <<" : x=" << O.x << " ;y=" << O.y << std::endl; +} + +void fangfangUnity() { + glm::vec3 vertices1[] = { + a,b,c,O + }; + fangfang(vertices1); + + glm::vec3 vertices2[] = { + d,e,O,c + }; + fangfang(vertices2); +} + +void sanjiao(glm::vec3 vertices[]) { + glBegin(GL_TRIANGLES); + glColor3f(16.0f / 255.0f, 53.0f / 255.0f, 86.0f / 255.0f); + glVertex3f(vertices[0].x, vertices[0].y, vertices[0].z); + glColor3f(16.0f / 255.0f, 53.0f / 255.0f, 86.0f / 255.0f); + glVertex3f(vertices[1].x, vertices[1].y, vertices[1].z); + glColor3f(160.0f / 255.0f, 185.0f / 255.0f, 208.0f / 255.0f); + glVertex3f(vertices[2].x, vertices[2].y, vertices[2].z); + glEnd(); +} + +void sanjiaoUnity() { + glm::vec3 vertices1[] = { + b,f,c + }; + sanjiao(vertices1); + + glm::vec3 vertices2[] = { + d,g,c + }; + sanjiao(vertices2); +} + +void banyuanUnity(int rotateAngle) { + constexpr int n = 360; + constexpr float pi = 3.1415926535897f; + for (int i = 0; i < n; i++) { + if (i < 90 || i >= 270) { + float angle = i / (float)n * pi * 2; + float angle_next = (i + 1) / (float)n * pi * 2; + + glm::vec3 k = glm::vec3(length * sinf(angle) + O.x, length * cosf(angle) + O.y, 0.0f); + glm::vec3 l = glm::vec3(length * sinf(angle_next) + O.x, length * cosf(angle_next) + O.y, 0.0f); + + glm::vec3 vertices1[] = { + rotate(k,O,rotateAngle),rotate(l,O,rotateAngle),O + }; + sanjiao(vertices1); + } + } +} + +glm::vec2 sangediandian[] = { //三个点的位置 + glm::vec2(-0.625f,-0.0244999f),//第二个点 + glm::vec2(0.125f,-0.0244999f),//第三个点 + glm::vec2(-0.25f,0.625f)//第一个短 +}; + +int jiaodu[] = { 150/*第一个该转的角度*/,270,390 }; //三个点的角度 + +int zhuangtai = -1; //向第几个点进发 + +bool blueRotateLock = false; +int blueRotateAngle = 0; + +static void render() { + + + constexpr float R = 0.5f; //R = 2 / 4。 Opengl宽2,宽4R + donut(0, R, int(150 / 2), int(210 / 2), 0); + donut(-R, -(R - 0.268f * R), int(30 / 2), int(90 / 2), 1); + if (blueRotateLock == false) { + donut(R, -(R - 0.268f * R), int(270 / 2), int(330 / 2), 2); + } + else { + if (blueRotateAngle <= 60) + blueRotateAngle++; + donut_two(R, -(R - 0.268f * R), int((270 + blueRotateAngle) / 2), int((330 + blueRotateAngle) / 2), 2, int(blueRotateAngle / 2)); + } + + if (dotUpdateLock == true) { + if (zhuangtai < 2) { + zhuangtai++; + dotUpdateLock = false; + } + } + + if ((zhuangtai != -1) && (!((zhuangtai == 2) && dotUpdateLock == true))) { //当状态开始后且没有到头的时候画图 + bresenham(int(O.x * 640.0f), int(O.y * 640.0f), int(sangediandian[zhuangtai].x * 640.0f), int(sangediandian[zhuangtai].y * 640.0f));//必须放在前面,不然Ox在dotHuiQu();里更新就是下一次 + dotHuiQu(); + dotUpdate(jiaodu[zhuangtai]); + + fangfangUnity(); + sanjiaoUnity(); + banyuanUnity(jiaodu[zhuangtai]); + } + else if (zhuangtai == 2) { + blueRotateLock = true; + } } int main() { if (!glfwInit()) { - const char *errmsg; + const char* errmsg; glfwGetError(&errmsg); if (!errmsg) errmsg = "(no error)"; std::cerr << "failed to initialize GLFW: " << errmsg << '\n'; @@ -61,18 +315,20 @@ int main() { } // Create window - GLFWwindow *window = glfwCreateWindow(640, 640, "Example", NULL, NULL); + GLFWwindow* window = glfwCreateWindow(640, 640, "Example", NULL, NULL); if (!window) { - const char *errmsg; + const char* errmsg; glfwGetError(&errmsg); if (!errmsg) errmsg = "(no error)"; std::cerr << "GLFW failed to create window: " << errmsg << '\n'; std::cerr << "==============================================\n"; if (!strcmp(errmsg, "X11: The DISPLAY environment variable is missing")) { std::cerr << "You seems not running with graphic display\n"; - } else if (!strcmp(errmsg, "WGL: The driver does not appear to support OpenGL")) { + } + else if (!strcmp(errmsg, "WGL: The driver does not appear to support OpenGL")) { std::cerr << "Please consider install an OpenGL driver, or use the mesa driver\n"; - } else if (!strcmp(errmsg, "WGL: Failed to create OpenGL context")) { + } + else if (!strcmp(errmsg, "WGL: Failed to create OpenGL context")) { std::cerr << "Your driver seems not supporting the required OpenGL version\n"; } std::cerr << "- If you have a physical graphic card (e.g. NVIDIA), install it from your graphic card vendor official website: http://www.nvidia.com/Download/index.aspx\n"; @@ -104,6 +360,8 @@ int main() { CHECK_GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); CHECK_GL(glPointSize(64.0f)); + + // start main game loop while (!glfwWindowShouldClose(window)) { // render graphics