Created
November 26, 2022 18:08
-
-
Save nagolove/80fa0996db520880cba81449b4c29f28 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <SDL2/SDL.h> | |
| #include <SDL2/SDL_events.h> | |
| #include <SDL2/SDL_keycode.h> | |
| #include <SDL2/SDL_rect.h> | |
| #include <SDL2/SDL_render.h> | |
| #include <stdbool.h> | |
| #include <stdlib.h> | |
| #include <assert.h> | |
| const int SCREEN_WIDTH = 1920; | |
| const int SCREEN_HEIGHT = 1080; | |
| typedef struct Transform { | |
| float a, b, c, d, tx, ty; | |
| } Transform; | |
| typedef struct Vect { | |
| float x, y; | |
| } Vect; | |
| /// Identity transform matrix. | |
| static const Transform TransformIdentity = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; | |
| /// Construct a new transform matrix. | |
| /// (a, b) is the x basis vector. | |
| /// (c, d) is the y basis vector. | |
| /// (tx, ty) is the translation. | |
| static inline Transform | |
| TransformNew(float a, float b, float c, float d, float tx, float ty) | |
| { | |
| Transform t = {a, b, c, d, tx, ty}; | |
| return t; | |
| } | |
| /// Construct a new transform matrix in transposed order. | |
| static inline Transform | |
| TransformNewTranspose(float a, float c, float tx, float b, float d, float ty) | |
| { | |
| Transform t = {a, b, c, d, tx, ty}; | |
| return t; | |
| } | |
| /// Get the inverse of a transform matrix. | |
| static inline Transform | |
| TransformInverse(Transform t) | |
| { | |
| float inv_det = 1.0/(t.a*t.d - t.c*t.b); | |
| return TransformNewTranspose( | |
| t.d*inv_det, -t.c*inv_det, (t.c*t.ty - t.tx*t.d)*inv_det, | |
| -t.b*inv_det, t.a*inv_det, (t.tx*t.b - t.a*t.ty)*inv_det | |
| ); | |
| } | |
| /// Multiply two transformation matrices. | |
| Transform | |
| TransformMult(Transform t1, Transform t2) | |
| { | |
| return TransformNewTranspose( | |
| t1.a*t2.a + t1.c*t2.b, t1.a*t2.c + t1.c*t2.d, t1.a*t2.tx + t1.c*t2.ty + t1.tx, | |
| t1.b*t2.a + t1.d*t2.b, t1.b*t2.c + t1.d*t2.d, t1.b*t2.tx + t1.d*t2.ty + t1.ty | |
| ); | |
| } | |
| /// Transform an absolute point. (i.e. a vertex) | |
| static inline Vect | |
| TransformPoint(Transform t, Vect p) | |
| { | |
| return (Vect){t.a*p.x + t.c*p.y + t.tx, t.b*p.x + t.d*p.y + t.ty}; | |
| } | |
| /// Transform a vector (i.e. a normal) | |
| static inline Vect | |
| TransformVect(Transform t, Vect v) | |
| { | |
| return (Vect){t.a*v.x + t.c*v.y, t.b*v.x + t.d*v.y}; | |
| } | |
| /// Create a transation matrix. | |
| static inline Transform | |
| TransformTranslate(Vect translate) | |
| { | |
| return TransformNewTranspose( | |
| 1.0, 0.0, translate.x, | |
| 0.0, 1.0, translate.y | |
| ); | |
| } | |
| /// Create a scale matrix. | |
| static inline Transform | |
| TransformScale(float scaleX, float scaleY) | |
| { | |
| return TransformNewTranspose( | |
| scaleX, 0.0, 0.0, | |
| 0.0, scaleY, 0.0 | |
| ); | |
| } | |
| /// Create a rotation matrix. | |
| static inline Transform | |
| TransformRotate(float radians) | |
| { | |
| Vect rot = { cos(radians), sin(radians)}; | |
| return TransformNewTranspose( | |
| rot.x, -rot.y, 0.0, | |
| rot.y, rot.x, 0.0 | |
| ); | |
| } | |
| /// Create a rigid transformation matrix. (transation + rotation) | |
| static inline Transform | |
| TransformRigid(Vect translate, float radians) | |
| { | |
| Vect rot = { cos(radians), sin(radians)}; | |
| return TransformNewTranspose( | |
| rot.x, -rot.y, translate.x, | |
| rot.y, rot.x, translate.y | |
| ); | |
| } | |
| /// Fast inverse of a rigid transformation matrix. | |
| static inline Transform | |
| TransformRigidInverse(Transform t) | |
| { | |
| return TransformNewTranspose( | |
| t.d, -t.c, (t.c*t.ty - t.tx*t.d), | |
| -t.b, t.a, (t.tx*t.b - t.a*t.ty) | |
| ); | |
| } | |
| //MARK: Miscellaneous (but useful) transformation matrices. | |
| // See source for documentation... | |
| static inline Transform | |
| TransformWrap(Transform outer, Transform inner) | |
| { | |
| return TransformMult(TransformInverse(outer), TransformMult(inner, outer)); | |
| } | |
| static inline Transform | |
| TransformWrapInverse(Transform outer, Transform inner) | |
| { | |
| return TransformMult(outer, TransformMult(inner, TransformInverse(outer))); | |
| } | |
| void make_elochka(SDL_Point *points, int *num) { | |
| assert(num); | |
| /*for (int j = 0; j < *num; j++) {*/ | |
| points[0].x = 0; | |
| points[0].y = 0; | |
| points[1].x = 300; | |
| points[1].y = 0; | |
| points[2].x = 150; | |
| points[2].y = 300; | |
| points[3].x = 0; | |
| points[3].y = 0; | |
| *num = 4; | |
| /*}*/ | |
| } | |
| struct Camera { | |
| int x, y; | |
| float scale, rot; | |
| }; | |
| void camera_apply(struct Camera *camera, SDL_Point *points, int num) { | |
| Transform t = TransformIdentity; | |
| printf("scale %f\n", camera->scale); | |
| t = TransformMult(t, TransformScale(camera->scale, camera->scale)); | |
| t = TransformMult(t, TransformRotate(camera->rot)); | |
| for (int j = 0; j < num; ++j) { | |
| Vect new = TransformPoint(t, (Vect) { points[j].x, points[j].y }); | |
| points[j].x = new.x; | |
| points[j].y = new.y; | |
| } | |
| } | |
| int main (int argc, char ** args) { | |
| if( SDL_Init( SDL_INIT_EVERYTHING ) != 0 ) | |
| { | |
| return 1; | |
| } | |
| SDL_Window* window = NULL; | |
| window = SDL_CreateWindow("Hello, SDL 2!",SDL_WINDOWPOS_UNDEFINED, | |
| SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, | |
| SDL_WINDOW_SHOWN); | |
| SDL_Renderer *rrr = SDL_CreateRenderer(window, 0, 0); | |
| if (window == NULL) { | |
| return 1; | |
| } | |
| int num = 8; | |
| /*SDL_Point *points = NULL;*/ | |
| struct Camera camera = { | |
| 0, 0, 1. | |
| }; | |
| SDL_Point *points = malloc(sizeof(points[0]) * num); | |
| SDL_Event ev = {0}; | |
| bool nonstop = true; | |
| while (nonstop) { | |
| while (SDL_PollEvent(&ev)) { | |
| if (ev.type == SDL_QUIT) { | |
| printf("Q\n"); | |
| } | |
| if (ev.type == SDL_KEYDOWN) { | |
| if (ev.key.keysym.sym == SDLK_ESCAPE) { | |
| nonstop = false; | |
| } | |
| if (ev.key.keysym.sym == SDLK_z) { | |
| printf("scale down\n"); | |
| camera.scale -= 0.01; | |
| } | |
| if (ev.key.keysym.sym == SDLK_x) { | |
| printf("scale up\n"); | |
| camera.scale += 0.01; | |
| } | |
| if (ev.key.keysym.sym == SDLK_c) { | |
| printf("scale up\n"); | |
| camera.scale = 1.; | |
| } | |
| if (ev.key.keysym.sym == SDLK_LEFT) { | |
| camera.rot -= 0.1; | |
| } | |
| if (ev.key.keysym.sym == SDLK_RIGHT) { | |
| printf("scale up\n"); | |
| camera.rot += 0.1; | |
| } | |
| } | |
| } | |
| make_elochka(points, &num); | |
| camera_apply(&camera, points, num); | |
| SDL_SetRenderDrawColor(rrr, 255, 255, 0, 255); | |
| SDL_RenderClear(rrr); | |
| SDL_SetRenderDrawColor(rrr, 255, 0, 0, 255); | |
| SDL_RenderDrawLines(rrr, points, num); | |
| SDL_RenderPresent(rrr); | |
| } | |
| free(points); | |
| /* | |
| SDL_Delay(2000); | |
| */ | |
| SDL_DestroyWindow(window); | |
| /*SDL_Quit();*/ | |
| return 0; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment