Skip to content

Instantly share code, notes, and snippets.

@nagolove
Created November 26, 2022 18:08
Show Gist options
  • Select an option

  • Save nagolove/80fa0996db520880cba81449b4c29f28 to your computer and use it in GitHub Desktop.

Select an option

Save nagolove/80fa0996db520880cba81449b4c29f28 to your computer and use it in GitHub Desktop.
#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