diff --git a/sirius.cpp b/sirius.cpp index 4b62bf7b01859e447456ddfcd7e53a7d00f6016d..80e0e48420577442862c8acfc940959a6c9f37b5 100644 --- a/sirius.cpp +++ b/sirius.cpp @@ -71,19 +71,19 @@ constexpr float degToRad(float d) { return d * M_PI / 180.0; } GPUProgram gpuProgram; // vertex and fragment shaders void setColor(vec3 color) { - int location = glGetUniformLocation(gpuProgram.getId(), "color"); - glUniform3f(location, color.x, color.y, color.z); // 3 floats + int location = glGetUniformLocation(gpuProgram.getId(), "color"); + glUniform3f(location, color.x, color.y, color.z); // 3 floats } void setupMVP() { - float MVPtransf[4][4] = {1, 0, 0, 0, // MVP matrix, - 0, 1, 0, 0, // row-major! - 0, 0, 1, 0, - 0, 0, 0, 1}; - - int location = glGetUniformLocation(gpuProgram.getId(), "MVP"); // Get the GPU location of uniform variable MVP - glUniformMatrix4fv(location, 1, GL_TRUE, - &MVPtransf[0][0]); // Load a 4x4 row-major float matrix to the specified location + float MVPtransf[4][4] = {1, 0, 0, 0, // MVP matrix, + 0, 1, 0, 0, // row-major! + 0, 0, 1, 0, + 0, 0, 0, 1}; + + int location = glGetUniformLocation(gpuProgram.getId(), "MVP"); // Get the GPU location of uniform variable MVP + glUniformMatrix4fv(location, 1, GL_TRUE, + &MVPtransf[0][0]); // Load a 4x4 row-major float matrix to the specified location } @@ -93,122 +93,122 @@ void setupMVP() { class Drawable { protected: - unsigned int vao; - unsigned int vbo; // vertex buffer object + unsigned int vao; + unsigned int vbo; // vertex buffer object public: - std::vector<vec2> vertices; - - virtual void draw() = 0; - - void init() { - glGenVertexArrays(1, &vao); // get 1 vao id - glBindVertexArray(vao); // make it active - - glGenBuffers(1, &vbo); // Generate 1 buffer - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, // Copy to GPU target - vertices.size() * sizeof(vec2), // # bytes - vertices.data(), // address - GL_STATIC_DRAW); // we do not change later - - glEnableVertexAttribArray(0); // AttribArray 0 - glVertexAttribPointer(0, // vbo -> AttribArray 0 - 2, GL_FLOAT, - GL_FALSE, // two floats/attrib, not fixed-point - 0, NULL); // stride, offset: tightly packed - } + std::vector<vec2> vertices; + + virtual void draw() = 0; + + void init() { + glGenVertexArrays(1, &vao); // get 1 vao id + glBindVertexArray(vao); // make it active + + glGenBuffers(1, &vbo); // Generate 1 buffer + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, // Copy to GPU target + vertices.size() * sizeof(vec2), // # bytes + vertices.data(), // address + GL_STATIC_DRAW); // we do not change later + + glEnableVertexAttribArray(0); // AttribArray 0 + glVertexAttribPointer(0, // vbo -> AttribArray 0 + 2, GL_FLOAT, + GL_FALSE, // two floats/attrib, not fixed-point + 0, NULL); // stride, offset: tightly packed + } }; class BaseCircle : public Drawable { public: - BaseCircle() { - // calculate all the vertices of the base circle: - float step = 360.0 / BASE_CIRCLE_SEGMENTS; - float currAngle = 0; + BaseCircle() { + // calculate all the vertices of the base circle: + float step = 360.0 / BASE_CIRCLE_SEGMENTS; + float currAngle = 0; - vertices.reserve(BASE_CIRCLE_SEGMENTS * 3); + vertices.reserve(BASE_CIRCLE_SEGMENTS * 3); - for (int i = 0; i < BASE_CIRCLE_SEGMENTS; i++) { - // for each of the triangles, calculate their points + for (int i = 0; i < BASE_CIRCLE_SEGMENTS; i++) { + // for each of the triangles, calculate their points - // middle point - vertices.emplace_back(0, 0); + // middle point + vertices.emplace_back(0, 0); - vertices.emplace_back(cos(degToRad(currAngle)), sin(degToRad(currAngle))); + vertices.emplace_back(cos(degToRad(currAngle)), sin(degToRad(currAngle))); - currAngle += step; - vertices.emplace_back(cos(degToRad(currAngle)), sin(degToRad(currAngle))); + currAngle += step; + vertices.emplace_back(cos(degToRad(currAngle)), sin(degToRad(currAngle))); + } } - } - void draw() override { - init(); - glBindVertexArray(vao); // Draw call - glDrawArrays(GL_TRIANGLES, 0, vertices.size()); - } + void draw() override { + init(); + glBindVertexArray(vao); // Draw call + glDrawArrays(GL_TRIANGLES, 0, vertices.size()); + } }; class Point : public Drawable { public: - vec2 p; + vec2 p; - Point(vec2 p) { - this->p = p; - vertices.emplace_back(p.x, p.y); - init(); - } + Point(vec2 p) { + this->p = p; + vertices.emplace_back(p.x, p.y); + init(); + } - vec2 inversion() { - return p / dot(p, p); - } + vec2 inversion() { + return p / dot(p, p); + } - void draw() override { + void draw() override { // printf("drawing points at %f %f\n", vertices[0].x, vertices[0].y); - glBindVertexArray(vao); - setColor(vec3(1, 0, 0)); + glBindVertexArray(vao); + setColor(vec3(1, 0, 0)); - glPointSize(10); - glDrawArrays(GL_POINTS, 0, 1); - } + glPointSize(10); + glDrawArrays(GL_POINTS, 0, 1); + } }; class Circle { public: - vec2 c; //center of the circle - float r; //radius of the circle + vec2 c; //center of the circle + float r; //radius of the circle - Circle(vec2 p1, vec2 p2, vec2 p3) { - vec2 n12 = p2 - p1; //normal vector for perpendicular bisector of p1 and p2 - float f12 = dot(n12, (p2 + p1) / 2); + Circle(vec2 p1, vec2 p2, vec2 p3) { + vec2 n12 = p2 - p1; //normal vector for perpendicular bisector of p1 and p2 + float f12 = dot(n12, (p2 + p1) / 2); - vec2 n23 = p3 - p2; //normal vector for perpendicular bisector of p1 and p2 - float f23 = dot(n23, (p2 + p3) / 2); + vec2 n23 = p3 - p2; //normal vector for perpendicular bisector of p1 and p2 + float f23 = dot(n23, (p2 + p3) / 2); - //coordinates for the circle's center - float cx = (f12 * n23.y - f23 * n12.y) / (n12.x * n23.y - n12.y * n23.x); - float cy = (f12 / n12.y) - (n12.x / n12.y) * (f12 * n23.y - n12.y * f23) / (n12.x * n23.y - n12.y * n23.x); + //coordinates for the circle's center + float cx = (f12 * n23.y - f23 * n12.y) / (n12.x * n23.y - n12.y * n23.x); + float cy = (f12 / n12.y) - (n12.x / n12.y) * (f12 * n23.y - n12.y * f23) / (n12.x * n23.y - n12.y * n23.x); - printf("%f %f\n", cx, cy); - c = vec2(cx, cy); - r = sqrtf((c.x - p1.x) * (c.x - p1.x) + (c.y - p1.y) * (c.y - p1.y)); - } + printf("%f %f\n", cx, cy); + c = vec2(cx, cy); + r = sqrtf((c.x - p1.x) * (c.x - p1.x) + (c.y - p1.y) * (c.y - p1.y)); + } }; inline float cross(vec2 a, vec2 b) { - return a.x * b.y - a.y * b.x; + return a.x * b.y - a.y * b.x; } inline bool onDifferentSides(vec2 p1, vec2 p2, vec2 q1, vec2 q2) { - vec2 v = p2 - p1; - return cross(v, q1 - p1) * cross(v, q2 - p1) < 0; + vec2 v = p2 - p1; + return cross(v, q1 - p1) * cross(v, q2 - p1) < 0; } inline bool intersectEachOther(vec2 p1, vec2 p2, vec2 q1, vec2 q2) { - return onDifferentSides(p1, p2, q1, q2) && - onDifferentSides(q1, q2, p1, p2); + return onDifferentSides(p1, p2, q1, q2) && + onDifferentSides(q1, q2, p1, p2); } class Triangulated : public Drawable { @@ -232,10 +232,10 @@ class Triangulated : public Drawable { vec2 currPotDiag1 = *getNextVertex(currVertex); vec2 currPotDiag2 = *getPreviousVertex(currVertex); for ( - auto currEdgeStart = getPreviousVertex(getPreviousVertex(currVertex)); - currEdgeStart != getNextVertex(getNextVertex(currVertex)); - currEdgeStart = getPreviousVertex(currEdgeStart) - ) + auto currEdgeStart = getPreviousVertex(getPreviousVertex(currVertex)); + currEdgeStart != getNextVertex(getNextVertex(currVertex)); + currEdgeStart = getPreviousVertex(currEdgeStart) + ) if (intersectEachOther(vec2(currEdgeStart->x, currEdgeStart->y), vec2(getNextVertex(currEdgeStart)->x, getNextVertex(currEdgeStart)->y), currPotDiag1, currPotDiag2)) { @@ -255,7 +255,7 @@ class Triangulated : public Drawable { for (auto currEdgeStart = remainingVertices.begin(); currEdgeStart != remainingVertices.end(); currEdgeStart = getNextVertex(currEdgeStart) - ) + ) if (intersectEachOther(currEdgeStart->x, *getNextVertex(currEdgeStart), middle, infinity)) numberOfIntersections++; @@ -294,108 +294,108 @@ public: }; class SiriusTriangle : public Drawable { - std::vector<Point> points; - std::vector<Triangulated> triangulated; + std::vector<Point> points; + std::vector<Triangulated> triangulated; public: - int n = 0; - - SiriusTriangle() = default; - - void addPoint(vec2 p) { - n++; - points.emplace_back(p); - if (n > 3) printf("Can't add 4th point to a triangle!\n"); - printf("%d\n", n); - if (n == 2) generateLineSegment(points[0], points[1]); - if (n == 3) { - generateLineSegment(points[2], points[0]); - generateLineSegment(points[1], points[2]); - triangulated.emplace_back(Triangulated(vertices)); - } + int n = 0; + + SiriusTriangle() = default; + + void addPoint(vec2 p) { + n++; + points.emplace_back(p); + if (n > 3) printf("Can't add 4th point to a triangle!\n"); + printf("%d\n", n); + if (n == 2) generateLineSegment(points[0], points[1]); + if (n == 3) { + generateLineSegment(points[2], points[0]); + generateLineSegment(points[1], points[2]); + triangulated.emplace_back(Triangulated(vertices)); + } - } - - void generateLineSegment(Point p1, Point p2) { - Circle c(p1.p, p2.p, p2.inversion()); - - // generating only points between p1 and p2 - float angle1 = atan2((p1.p - c.c).y, (p1.p - c.c).x); - printf("Angle for p1 in the circle is %f\n", angle1); - float angle2 = atan2((p2.p - c.c).y, (p2.p - c.c).x); - printf("Angle for p2 in the circle is %f\n", angle2); - - //normalize both angles to [0, 2*PI) - if (angle1 < 0) angle1 += 2 * M_PI; - if (angle2 < 0) angle2 += 2 * M_PI; - - //rotate both angles by 180 degress and check if the difference is smaller then - float altAngle1 = angle1 + M_PI; - if (altAngle1 > 2 * M_PI) altAngle1 -= 2 * M_PI; - float altAngle2 = angle2 + M_PI; - if (altAngle2 > 2 * M_PI) altAngle2 -= 2 * M_PI; - - float angleDiff; - if (fabs(angle1 - angle2) < fabs(altAngle1 - altAngle2)) - angleDiff = (angle1 - angle2); - else - angleDiff = (altAngle1 - altAngle2); - - //can be negative - float step = angleDiff / SIRIUS_CIRCLE_SEGMENTS; - - //start from angle2 - float curr = angle2; - - for (int i = 0; i < SIRIUS_CIRCLE_SEGMENTS; i++) { - vertices.emplace_back(vec2( - c.r * cos(curr) + c.c.x, - c.r * sin(curr) + c.c.y - )); - curr += step; } - } - void draw() override { - //filling out the triangulated area - if (n == 3) - triangulated[0].draw(); + void generateLineSegment(Point p1, Point p2) { + Circle c(p1.p, p2.p, p2.inversion()); + // generating only points between p1 and p2 + float angle1 = atan2((p1.p - c.c).y, (p1.p - c.c).x); + printf("Angle for p1 in the circle is %f\n", angle1); + float angle2 = atan2((p2.p - c.c).y, (p2.p - c.c).x); + printf("Angle for p2 in the circle is %f\n", angle2); + + //normalize both angles to [0, 2*PI) + if (angle1 < 0) angle1 += 2 * M_PI; + if (angle2 < 0) angle2 += 2 * M_PI; + + //rotate both angles by 180 degress and check if the difference is smaller then + float altAngle1 = angle1 + M_PI; + if (altAngle1 > 2 * M_PI) altAngle1 -= 2 * M_PI; + float altAngle2 = angle2 + M_PI; + if (altAngle2 > 2 * M_PI) altAngle2 -= 2 * M_PI; + + float angleDiff; + if (fabs(angle1 - angle2) < fabs(altAngle1 - altAngle2)) + angleDiff = (angle1 - angle2); + else + angleDiff = (altAngle1 - altAngle2); - //Time to draw the edges - if (n == 3) { - init(); - glBindVertexArray(vao); // Draw call - setColor(vec3(0.6, 0.2, 0.6)); - glDrawArrays(GL_LINE_LOOP, 0, vertices.size()); + //can be negative + float step = angleDiff / SIRIUS_CIRCLE_SEGMENTS; + + //start from angle2 + float curr = angle2; + + for (int i = 0; i < SIRIUS_CIRCLE_SEGMENTS; i++) { + vertices.emplace_back(vec2( + c.r * cos(curr) + c.c.x, + c.r * sin(curr) + c.c.y + )); + curr += step; + } } + void draw() override { + //filling out the triangulated area + if (n == 3) + triangulated[0].draw(); + - for (auto &point: points) - point.draw(); - } + //Time to draw the edges + if (n == 3) { + init(); + glBindVertexArray(vao); // Draw call + setColor(vec3(0.6, 0.2, 0.6)); + glDrawArrays(GL_LINE_LOOP, 0, vertices.size()); + } + + + for (auto &point: points) + point.draw(); + } }; class SiriusTriangleManager { public: - std::vector<SiriusTriangle> triangles; - int currTriangle = 0; - int currPoints = 0; + std::vector<SiriusTriangle> triangles; + int currTriangle = 0; + int currPoints = 0; - SiriusTriangleManager() = default; + SiriusTriangleManager() = default; - void addPoint(vec2 p) { - if (currPoints == 0) triangles.emplace_back(SiriusTriangle()); - triangles[currTriangle].addPoint(p); - currPoints++; + void addPoint(vec2 p) { + if (currPoints == 0) triangles.emplace_back(SiriusTriangle()); + triangles[currTriangle].addPoint(p); + currPoints++; - if (currPoints == 3) currTriangle++, currPoints = 0; - } + if (currPoints == 3) currTriangle++, currPoints = 0; + } - void draw() { - for (auto triangle: triangles) - triangle.draw(); - } + void draw() { + for (auto triangle: triangles) + triangle.draw(); + } }; BaseCircle baseCircle = BaseCircle(); @@ -403,42 +403,42 @@ SiriusTriangleManager siriusTriangleManager = SiriusTriangleManager(); // Initialization, create an OpenGL context void onInitialization() { - glViewport(0, 0, windowWidth, windowHeight); - - printf("%d", intersectEachOther( - vec2(0, 0), - vec2(100, 0), - vec2(2, 2), - vec2(2, -4) - )); - - baseCircle.init(); - siriusTriangleManager.addPoint(vec2(-0.6, 0.4)); - siriusTriangleManager.addPoint(vec2(-0.8, -0.2)); - siriusTriangleManager.addPoint(vec2(-0.2, -0.6)); - - // create program for the GPU - gpuProgram.create(vertexSource, fragmentSource, "outColor"); + glViewport(0, 0, windowWidth, windowHeight); + + printf("%d", intersectEachOther( + vec2(0, 0), + vec2(100, 0), + vec2(2, 2), + vec2(2, -4) + )); + + baseCircle.init(); + siriusTriangleManager.addPoint(vec2(-0.6, 0.4)); + siriusTriangleManager.addPoint(vec2(-0.8, -0.2)); + siriusTriangleManager.addPoint(vec2(-0.2, -0.6)); + + // create program for the GPU + gpuProgram.create(vertexSource, fragmentSource, "outColor"); } // Window has become invalid: Redraw void onDisplay() { - glClearColor(0, 0, 0.4, 1); // background color - glClear(GL_COLOR_BUFFER_BIT); // clear frame buffer + glClearColor(0, 0, 0.4, 1); // background color + glClear(GL_COLOR_BUFFER_BIT); // clear frame buffer - setupMVP(); + setupMVP(); - setColor(vec3(0, 0.3, 0.5)); + setColor(vec3(0, 0.3, 0.5)); - baseCircle.draw(); - siriusTriangleManager.draw(); + baseCircle.draw(); + siriusTriangleManager.draw(); - glutSwapBuffers(); // exchange buffers for double buffering + glutSwapBuffers(); // exchange buffers for double buffering } // Key of ASCII code pressed void onKeyboard(unsigned char key, int pX, int pY) { - if (key == 'd') glutPostRedisplay(); // if d, invalidate display, i.e. redraw + if (key == 'd') glutPostRedisplay(); // if d, invalidate display, i.e. redraw } // Key of ASCII code released @@ -448,51 +448,51 @@ void onKeyboardUp(unsigned char key, int pX, int pY) { // Move mouse with key pressed void onMouseMotion(int pX, int pY) { // pX, pY are the pixel coordinates of the cursor in the coordinate system of the operation system - // Convert to normalized device space - float cX = 2.0f * pX / windowWidth - 1; // flip y axis - float cY = 1.0f - 2.0f * pY / windowHeight; - printf("Mouse moved to (%3.2f, %3.2f)\n", cX, cY); + // Convert to normalized device space + float cX = 2.0f * pX / windowWidth - 1; // flip y axis + float cY = 1.0f - 2.0f * pY / windowHeight; + printf("Mouse moved to (%3.2f, %3.2f)\n", cX, cY); } // Mouse click event void onMouse(int button, int state, int pX, int pY) { // pX, pY are the pixel coordinates of the cursor in the coordinate system of the operation system - // Convert to normalized device space - float cX = 2.0f * pX / windowWidth - 1; // flip y axis - float cY = 1.0f - 2.0f * pY / windowHeight; - - char *buttonStat; - switch (state) { - case GLUT_DOWN: - buttonStat = "pressed"; - break; - case GLUT_UP: - buttonStat = "released"; - break; - } - - switch (button) { - case GLUT_LEFT_BUTTON: - printf("Left button %s at (%3.2f, %3.2f)\n", buttonStat, cX, cY); - break; - case GLUT_MIDDLE_BUTTON: - printf("Middle button %s at (%3.2f, %3.2f)\n", buttonStat, cX, cY); - break; - case GLUT_RIGHT_BUTTON: - printf("Right button %s at (%3.2f, %3.2f)\n", buttonStat, cX, cY); - break; - } - - if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON) { - siriusTriangleManager.addPoint(vec2(cX, cY)); - siriusTriangleManager.draw(); - glutPostRedisplay(); - } + // Convert to normalized device space + float cX = 2.0f * pX / windowWidth - 1; // flip y axis + float cY = 1.0f - 2.0f * pY / windowHeight; + + char *buttonStat; + switch (state) { + case GLUT_DOWN: + buttonStat = "pressed"; + break; + case GLUT_UP: + buttonStat = "released"; + break; + } + + switch (button) { + case GLUT_LEFT_BUTTON: + printf("Left button %s at (%3.2f, %3.2f)\n", buttonStat, cX, cY); + break; + case GLUT_MIDDLE_BUTTON: + printf("Middle button %s at (%3.2f, %3.2f)\n", buttonStat, cX, cY); + break; + case GLUT_RIGHT_BUTTON: + printf("Right button %s at (%3.2f, %3.2f)\n", buttonStat, cX, cY); + break; + } + + if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON) { + siriusTriangleManager.addPoint(vec2(cX, cY)); + siriusTriangleManager.draw(); + glutPostRedisplay(); + } } // Idle event indicating that some time elapsed: do animation here void onIdle() { - long time = glutGet(GLUT_ELAPSED_TIME); // elapsed time since the start of the program + long time = glutGet(GLUT_ELAPSED_TIME); // elapsed time since the start of the program } #include <utility>