Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* By Blackjack on CurtPalme.com Forums, November 2022.
- * This file is hereby explicitly in the public domain.
- *
- * Compile: gcc -o pentagon pentagon.c -lGL -lglut -lm
- *
- * Keyboard shortcuts:
- * s - swap the color of the background and the foreground
- * h - show dragging handles at the vertices of the pentagon
- * f - toggle full screen
- * c - reset/re-center the pentagon
- * m - it's supposed to flip it but it doesn't work
- * +/- - increase/decrease intensity of the color
- * = - reset intensity of the color
- *
- * mouse: click and drag on a vertex to move it. last clicked vertex = "selected vertex"
- * arrow keys - move the selected vertex in the direction of the arrow by 1px, or 10px if SHIFT is held.
- */
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <GL/glut.h>
- static int g_WindowWidth = 1920;
- static int g_WindowHeight = 1080;
- static int g_MouseX = 0;
- static int g_MouseY = 0;
- static bool g_InvertColor = false;
- static bool g_ShowHandles = false;
- static bool g_FullScreen = false;
- static float g_Intensity = 1.0f;
- typedef struct {
- float x;
- float y;
- } vec2;
- struct pentagon {
- vec2 tip;
- vec2 left;
- vec2 right;
- vec2 bottomleft;
- vec2 bottomright;
- } g_Pentagon;
- /* The coordinates of the current point of the polygon that we're dragging. */
- static vec2 *g_CurrentPoint = NULL;
- static vec2 *g_SelectedPoint = NULL;
- /* The offset of the current point from the mouse pointer - this is used so that the point doesn't "snap"
- * to the mouse cursor when we start dragging.
- */
- static vec2 g_Offset = {0, 0};
- vec2 *findClosestPoint(struct pentagon *p, int x, int y) {
- int i;
- float distX, distY, dist;
- float bestDist = -1;
- vec2 *bestVec = NULL;
- vec2 *vecs[5] = { &p->tip, &p->left, &p->right, &p->bottomleft, &p->bottomright };
- for (i = 0; i < 5; i++) {
- distX = vecs[i]->x - x;
- distY = vecs[i]->y - y;
- dist = fabs(sqrt((distX * distX) + (distY * distY)));
- if ((bestDist == -1 || dist < bestDist) && dist <= 50) {
- bestDist = dist;
- bestVec = vecs[i];
- }
- }
- return bestVec;
- }
- void displayPentagon(struct pentagon *p) {
- if (g_InvertColor) {
- glColor4f(0, 0, 0, 1.0);
- } else {
- glColor4f(0, g_Intensity, 0, 1.0);
- }
- glBegin(GL_TRIANGLE_FAN);
- glVertex2f(p->tip.x, p->tip.y);
- glVertex2f(p->right.x, p->right.y);
- glVertex2f(p->bottomright.x, p->bottomright.y);
- glVertex2f(p->bottomright.x, p->bottomright.y);
- glVertex2f(p->bottomleft.x, p->bottomleft.y);
- glVertex2f(p->left.x, p->left.y);
- glEnd();
- if (g_ShowHandles) {
- glPointSize(50.0);
- glColor4f(1, 0, 0, 1);
- glBegin(GL_POINTS);
- glVertex2f(p->tip.x, p->tip.y);
- glVertex2f(p->right.x, p->right.y);
- glVertex2f(p->left.x, p->left.y);
- glVertex2f(p->bottomright.x, p->bottomright.y);
- glVertex2f(p->bottomleft.x, p->bottomleft.y);
- glEnd();
- }
- }
- void setup() {
- g_Pentagon.tip = (vec2) {g_WindowWidth / 2, 0};
- g_Pentagon.left = (vec2) {0, g_WindowHeight / 2};
- g_Pentagon.right = (vec2) {g_WindowWidth, g_WindowHeight / 2};
- g_Pentagon.bottomleft = (vec2) {g_WindowWidth / 4, g_WindowHeight};
- g_Pentagon.bottomright = (vec2) {g_WindowWidth - (g_WindowWidth / 4), g_WindowHeight};
- }
- void display() {
- if (g_InvertColor) {
- glClearColor(0, g_Intensity, 0, 1);
- } else {
- glClearColor(0, 0, 0, 1);
- }
- glClear(GL_COLOR_BUFFER_BIT);
- displayPentagon(&g_Pentagon);
- glutSwapBuffers();
- glutPostRedisplay();
- }
- void resizeCallback(int width, int height) {
- g_WindowWidth = width;
- g_WindowHeight = height;
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glViewport(0, 0, g_WindowWidth, g_WindowHeight);
- glOrtho(0, g_WindowWidth, g_WindowHeight, 0, 0.0, 100.0);
- }
- void mouseCallback(int button, int state, int x, int y) {
- g_MouseX = x;
- g_MouseY = y;
- if (state == GLUT_DOWN) {
- g_CurrentPoint = findClosestPoint(&g_Pentagon, x, y);
- g_SelectedPoint = g_CurrentPoint;
- if (g_CurrentPoint != NULL) {
- g_Offset = (vec2) { (g_CurrentPoint->x - x), (g_CurrentPoint->y - y) };
- }
- } else {
- g_CurrentPoint = NULL;
- }
- }
- void mouseMoveCallback(int x, int y) {
- g_MouseX = x;
- g_MouseY = y;
- if (g_CurrentPoint != NULL) {
- g_CurrentPoint->x = x + g_Offset.x;
- g_CurrentPoint->y = y + g_Offset.y;
- }
- }
- void keyboardCallback(unsigned char c, int x, int y) {
- switch (c) {
- case 's':
- g_InvertColor = !g_InvertColor;
- break;
- case 'h':
- g_ShowHandles = !g_ShowHandles;
- break;
- case 'f':
- g_FullScreen = !g_FullScreen;
- if (g_FullScreen) {
- glutFullScreen();
- } else {
- glutReshapeWindow(g_WindowWidth, g_WindowHeight);
- }
- break;
- case 'c':
- setup();
- break;
- case 'm':
- g_Pentagon = (struct pentagon) {
- .tip = g_Pentagon.tip,
- .left = g_Pentagon.right,
- .right = g_Pentagon.left,
- .bottomleft = g_Pentagon.bottomright,
- .bottomright = g_Pentagon.bottomleft
- };
- break;
- case '+':
- g_Intensity += 0.01;
- break;
- case '-':
- g_Intensity -= 0.01;
- break;
- case '=':
- g_Intensity = 1.0;
- break;
- }
- }
- void specialKeyboardCallback(int key, int x, int y) {
- float mod = 1.0;
- if (g_SelectedPoint == NULL) {
- return;
- }
- if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
- mod = 10.0;
- }
- switch (key) {
- case GLUT_KEY_RIGHT:
- g_SelectedPoint->x += mod;
- break;
- case GLUT_KEY_LEFT:
- g_SelectedPoint->x -= mod;
- break;
- case GLUT_KEY_UP:
- g_SelectedPoint->y -= mod;
- break;
- case GLUT_KEY_DOWN:
- g_SelectedPoint->y += mod;
- break;
- }
- }
- int main(int argc, char *argv[]) {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
- glutInitWindowSize(g_WindowWidth, g_WindowHeight);
- glutCreateWindow("Pentagon");
- glutReshapeFunc(resizeCallback);
- glutDisplayFunc(display);
- glutMouseFunc(mouseCallback);
- glutKeyboardFunc(keyboardCallback);
- glutSpecialFunc(specialKeyboardCallback);
- glutMotionFunc(mouseMoveCallback);
- setup();
- glutMainLoop();
- return 0;
- }
Add Comment
Please, Sign In to add comment