From c7f5780d3b67da9c57d658994bcff298e6a1cac9 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Sun, 29 Mar 2026 09:15:37 +0300 Subject: chore: Rework file layout and add make script --- .gitignore | 4 ++ AnimationRender/FrameCallback.h | 2 +- FrameRender/FrameRender.h | 2 +- FrameRender/PixelCallback.h | 2 +- RGBImage.c | 83 --------------------------- RGBImage.h | 35 ------------ RGBImage/RGBImage.c | 83 +++++++++++++++++++++++++++ RGBImage/RGBImage.h | 35 ++++++++++++ graphics.c | 121 ---------------------------------------- make.sh | 52 +++++++++++++++++ renders/anim_graph_rotate.c | 112 +++++++++++++++++++++++++++++++++++++ 11 files changed, 289 insertions(+), 242 deletions(-) create mode 100644 .gitignore delete mode 100644 RGBImage.c delete mode 100644 RGBImage.h create mode 100644 RGBImage/RGBImage.c create mode 100644 RGBImage/RGBImage.h delete mode 100644 graphics.c create mode 100755 make.sh create mode 100644 renders/anim_graph_rotate.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5dece76 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +anim_* +!renders/anim_* + +*.mp4 diff --git a/AnimationRender/FrameCallback.h b/AnimationRender/FrameCallback.h index b3292bb..a48b4b6 100644 --- a/AnimationRender/FrameCallback.h +++ b/AnimationRender/FrameCallback.h @@ -2,7 +2,7 @@ #define _FRAME_CALLBACK #include "../global.h" -#include "../RGBImage.h" +#include "../RGBImage/RGBImage.h" struct FrameContext { u32 frame; diff --git a/FrameRender/FrameRender.h b/FrameRender/FrameRender.h index 09037cb..3f2eeb1 100644 --- a/FrameRender/FrameRender.h +++ b/FrameRender/FrameRender.h @@ -2,7 +2,7 @@ #define _FRAME_RENDER #include "../global.h" -#include "../RGBImage.h" +#include "../RGBImage/RGBImage.h" #include "PixelCallback.h" void RenderFrame(RGBImage buffer, const PixelCallback** callbacks, usize sizeCallbacks); diff --git a/FrameRender/PixelCallback.h b/FrameRender/PixelCallback.h index b0aee1f..a1ce740 100644 --- a/FrameRender/PixelCallback.h +++ b/FrameRender/PixelCallback.h @@ -2,7 +2,7 @@ #define _PIXEL_CALLBACK #include "../global.h" -#include "../RGBImage.h" +#include "../RGBImage/RGBImage.h" struct PixelContext { i32 x; diff --git a/RGBImage.c b/RGBImage.c deleted file mode 100644 index 2896d72..0000000 --- a/RGBImage.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "RGBImage.h" -#include -#include -#include - -void -ARGB_set(ARGB* rgb, color color) { - rgb->a = (0xFF000000 & color) >> 24; - rgb->r = (0x00FF0000 & color) >> 16; - rgb->g = (0x0000FF00 & color) >> 8; - rgb->b = (0x000000FF & color); -} - -void -ARGB_merge(ARGB* bottom, color top) { - ARGB temp; - ARGB_set(&temp, top); - ARGB_mergeARGB(bottom, temp); -} - -void -ARGB_mergeARGB(ARGB* bottom, ARGB top) { - bottom->a = 255; - double perc = top.a / 255.0; - - bottom->r = (bottom->r * (1.0 - perc)) + (top.r * perc); - bottom->g = (bottom->g * (1.0 - perc)) + (top.g * perc); - bottom->b = (bottom->b * (1.0 - perc)) + (top.b * perc); -} - -RGBImage -RGBImage_new(u32 width, u32 height) { - return (RGBImage){ - .width = width, - .height = height, - .img = malloc(sizeof(ARGB) * width * height) - }; -} - -void -RGBImage_free(RGBImage img) { - free(img.img); -} - -void -RGBImage_delete(RGBImage* img) { - RGBImage_free(*img); - img->width = img->height = 0; - img->img = NULL; -} - -ARGB* -RGBImage_at(RGBImage img, int row, int col) { - return img.img + (row % img.height) * img.width + col % img.width; -} - -int -ppm6_write(FILE* f, RGBImage img) { - fprintf(f, "P6\n%d %d\n255\n", img.width, img.height); - size_t size = img.width * img.height; - for (size_t i = 0; i < size; ++i) { - fputc(img.img[i].r, f); - fputc(img.img[i].g, f); - fputc(img.img[i].b, f); - } - return fflush(f); -} - -RGBImage -ppm_read(FILE* f) { - u32 type, width, height, colors; - fscanf(f, "P%d\n%d %d\n%d\n", &type, &width, &height, &colors); - - RGBImage img = RGBImage_new(width, height); - ARGB* pixel = img.img; - for (size_t i = img.width * img.height; i > 0; --i, ++pixel) { - if (type == 3) { - pixel->a = 0xFF; - fscanf(f, "%d %d %d ", &pixel->r, &pixel->g, &pixel->b); - } - } - return img; -} diff --git a/RGBImage.h b/RGBImage.h deleted file mode 100644 index e2f9043..0000000 --- a/RGBImage.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _RGBIMAGE -#define _RGBIMAGE - -#include "global.h" -#include - -typedef uint8_t byte; -typedef uint32_t color; - -typedef struct ARGB { - byte a; - byte r; - byte g; - byte b; -} ARGB; - -void ARGB_merge(ARGB* bottom, color top); -void ARGB_mergeARGB(ARGB* bottom, ARGB top); -void ARGB_set(ARGB* rgb, color color); - -typedef struct RGBImage { - u32 width; - u32 height; - ARGB* img; -} RGBImage; - -RGBImage RGBImage_new(u32 width, u32 height); -void RGBImage_free(RGBImage img); -void RGBImage_delete(RGBImage* img); -ARGB* RGBImage_at(RGBImage img, int row, int col); - -int ppm6_write(FILE* f, RGBImage img); -RGBImage ppm_read(FILE* f); - -#endif /* _RGBIMAGE */ diff --git a/RGBImage/RGBImage.c b/RGBImage/RGBImage.c new file mode 100644 index 0000000..2896d72 --- /dev/null +++ b/RGBImage/RGBImage.c @@ -0,0 +1,83 @@ +#include "RGBImage.h" +#include +#include +#include + +void +ARGB_set(ARGB* rgb, color color) { + rgb->a = (0xFF000000 & color) >> 24; + rgb->r = (0x00FF0000 & color) >> 16; + rgb->g = (0x0000FF00 & color) >> 8; + rgb->b = (0x000000FF & color); +} + +void +ARGB_merge(ARGB* bottom, color top) { + ARGB temp; + ARGB_set(&temp, top); + ARGB_mergeARGB(bottom, temp); +} + +void +ARGB_mergeARGB(ARGB* bottom, ARGB top) { + bottom->a = 255; + double perc = top.a / 255.0; + + bottom->r = (bottom->r * (1.0 - perc)) + (top.r * perc); + bottom->g = (bottom->g * (1.0 - perc)) + (top.g * perc); + bottom->b = (bottom->b * (1.0 - perc)) + (top.b * perc); +} + +RGBImage +RGBImage_new(u32 width, u32 height) { + return (RGBImage){ + .width = width, + .height = height, + .img = malloc(sizeof(ARGB) * width * height) + }; +} + +void +RGBImage_free(RGBImage img) { + free(img.img); +} + +void +RGBImage_delete(RGBImage* img) { + RGBImage_free(*img); + img->width = img->height = 0; + img->img = NULL; +} + +ARGB* +RGBImage_at(RGBImage img, int row, int col) { + return img.img + (row % img.height) * img.width + col % img.width; +} + +int +ppm6_write(FILE* f, RGBImage img) { + fprintf(f, "P6\n%d %d\n255\n", img.width, img.height); + size_t size = img.width * img.height; + for (size_t i = 0; i < size; ++i) { + fputc(img.img[i].r, f); + fputc(img.img[i].g, f); + fputc(img.img[i].b, f); + } + return fflush(f); +} + +RGBImage +ppm_read(FILE* f) { + u32 type, width, height, colors; + fscanf(f, "P%d\n%d %d\n%d\n", &type, &width, &height, &colors); + + RGBImage img = RGBImage_new(width, height); + ARGB* pixel = img.img; + for (size_t i = img.width * img.height; i > 0; --i, ++pixel) { + if (type == 3) { + pixel->a = 0xFF; + fscanf(f, "%d %d %d ", &pixel->r, &pixel->g, &pixel->b); + } + } + return img; +} diff --git a/RGBImage/RGBImage.h b/RGBImage/RGBImage.h new file mode 100644 index 0000000..8980f7b --- /dev/null +++ b/RGBImage/RGBImage.h @@ -0,0 +1,35 @@ +#ifndef _RGBIMAGE +#define _RGBIMAGE + +#include "../global.h" +#include + +typedef uint8_t byte; +typedef uint32_t color; + +typedef struct ARGB { + byte a; + byte r; + byte g; + byte b; +} ARGB; + +void ARGB_merge(ARGB* bottom, color top); +void ARGB_mergeARGB(ARGB* bottom, ARGB top); +void ARGB_set(ARGB* rgb, color color); + +typedef struct RGBImage { + u32 width; + u32 height; + ARGB* img; +} RGBImage; + +RGBImage RGBImage_new(u32 width, u32 height); +void RGBImage_free(RGBImage img); +void RGBImage_delete(RGBImage* img); +ARGB* RGBImage_at(RGBImage img, int row, int col); + +int ppm6_write(FILE* f, RGBImage img); +RGBImage ppm_read(FILE* f); + +#endif /* _RGBIMAGE */ diff --git a/graphics.c b/graphics.c deleted file mode 100644 index 678a26e..0000000 --- a/graphics.c +++ /dev/null @@ -1,121 +0,0 @@ -/* gcc -std=c99 *.c -lm && ./a.out | mpv --no-correct-pts --container-fps-override=30 - - * gcc -std=c99 *.c -lm && ./a.out | ffmpeg -r 30 -i - output.mp4 - */ - -#include "AnimationRender/AnimationRender.h" -#include "AnimationRender/F_Draw.h" -#include "AnimationRender/F_FrameRange.h" -#include "AnimationRender/F_Interpolate.h" -#include "AnimationRender/FrameCallback.h" -#include "FrameRender/FrameRender.h" -#include "FrameRender/P_Checker.h" -#include "FrameRender/P_Circle.h" -#include "FrameRender/P_Image.h" -#include "FrameRender/P_LineSegment.h" -#include "FrameRender/P_Square.h" -#include "FrameRender/P_TransformCenter.h" -#include "FrameRender/P_TransformRotate.h" -#include "FrameRender/PixelCallback.h" -#include "RGBImage.h" -#include - -int -main() { - u32 width = 512; - u32 height = 512; - const u32 FPS = 60; - u32 frames = FPS * 5; - - PixelCallback* child; - TransformCenter childLeft = { .centerX = width / 4, .centerY = height * 3 / 4, }; - TransformCenter childRight = { .centerX = width * 3 / 4, .centerY = height * 3 / 4, }; - - PixelCallback* segment; - LineSegment segmentRight = { - .aX = width / 2, .aY = height / 4, - .bX = width * 3 / 4, .bY = height * 3 / 4, - .width = 20, .color = 0xFFFF00FF, - }; - LineSegment segmentLeft = { - .aX = width / 2, .aY = height / 4, - .bX = width / 4, .bY = height * 3 / 4, - .width = 20, .color = 0xFF0088FF, - }; - - PixelCallback* callbacks[] = { - /* Background */ - Square_setup((Square){ - .size = width, .color = 0xFFF0F0F0, - }), - /* Connecting line */ - NULL, - segment = LineSegment_setup(segmentRight), - /* Root node */ - TransformCenter_setup((TransformCenter){ - .centerX = width / 2, .centerY = height / 4, - }), - Circle_setup((Circle){ - .radius = 60, .color = 0xFFFF0000, - }), - /* Child node */ - NULL, - child = TransformCenter_setup(childRight), - Circle_setup((Circle){ - .radius = 60, .color = 0xFF00FF00, - }), - }; - u32 sizeCallbacks = sizeof(callbacks) / sizeof(*callbacks); - - FrameCallback* frameCallbacks[] = { - /* Move right to left */ - FrameRange_setup((FrameRange){ - .startFrame = frames / 3 - FPS, .endFrame = frames / 3, - }), - Interpolate_setup((Interpolate){ - .startValue = &childRight, .endValue = &childLeft, - .value = child->callback_self, - .interpolate = (f_interpolate)Interpolate_TransformCenter, - }), - Interpolate_setup((Interpolate){ - .startValue = &segmentRight, .endValue = &segmentLeft, - .value = segment->callback_self, - .interpolate = (f_interpolate)Interpolate_LineSegment, - }), - /* Move left to right */ - NULL, - FrameRange_setup((FrameRange){ - .startFrame = frames * 2 / 3 - FPS, .endFrame = frames * 2 / 3, - }), - Interpolate_setup((Interpolate){ - .startValue = &childLeft, .endValue = &childRight, - .value = child->callback_self, - .interpolate = (f_interpolate)Interpolate_TransformCenter, - }), - Interpolate_setup((Interpolate){ - .startValue = &segmentLeft, .endValue = &segmentRight, - .value = segment->callback_self, - .interpolate = (f_interpolate)Interpolate_LineSegment, - }), - /* Render */ - NULL, - Draw_setup((Draw){ - .callbacks = (const PixelCallback**)callbacks, .sizeCallbacks = sizeCallbacks, - }), - }; - u32 sizeFrameCallbacks = sizeof(frameCallbacks) / sizeof(*frameCallbacks); - - RenderAnimation(width, height, frames, (const FrameCallback**)frameCallbacks, sizeFrameCallbacks); - - for (u32 i = 0; i < sizeCallbacks; ++i) { - if (callbacks[i] == NULL) continue; - free(callbacks[i]->callback_self); - free(callbacks[i]); - } - for (u32 i = 0; i < sizeFrameCallbacks; ++i) { - if (frameCallbacks[i] == NULL) continue; - free(frameCallbacks[i]->callback_self); - free(frameCallbacks[i]); - } - - return 0; -} diff --git a/make.sh b/make.sh new file mode 100755 index 0000000..b499eef --- /dev/null +++ b/make.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +: ${CC:=gcc} +: ${CARGS:=-std=c99 -lm -O3} +: ${FPS:=30} +: ${PLAYER:=mpv} +: ${PLAYERARGS:=--no-correct-pts --container-fps-override=\$FPS -} +: ${RENDER:=ffmpeg} +: ${RENDERARGS:=-r \$FPS -i - \$bin.mp4} + +binname() { + name="${1%%.c}" + echo "${name##*/}" +} + +make_compile() { + bin="$(binname "$1")" + $(eval "echo \"$CC\"") $(eval "echo \"$CARGS\"") AnimationRender/*.c FrameRender/*.c RGBImage/*.c "$1" -o "$bin" +} + +make_run() { + bin="$(binname "$1")" + "./$bin" | $(eval "echo \"$PLAYER\"") $(eval "echo \"$PLAYERARGS\"") +} + +make_render() { + bin="$(binname "$1")" + "./$bin" | $(eval "echo \"$RENDER\"") $(eval "echo \"$RENDERARGS\"") +} + +if [ ! -f "$2" ] +then + echo "'$2' is not valid! Must be the path to a C file which contains main function." + exit 2 +fi + +case "$1" in + (compile) + make_compile "$2" + ;; + (run) + make_compile "$2" + make_run "$2" + ;; + (render) + make_compile "$2" + make_render "$2" + ;; + (*) + echo "Unrecognised action '$1'!" + exit 1 +esac diff --git a/renders/anim_graph_rotate.c b/renders/anim_graph_rotate.c new file mode 100644 index 0000000..e0b3a61 --- /dev/null +++ b/renders/anim_graph_rotate.c @@ -0,0 +1,112 @@ +#include "../AnimationRender/AnimationRender.h" +#include "../AnimationRender/F_Draw.h" +#include "../AnimationRender/F_FrameRange.h" +#include "../AnimationRender/F_Interpolate.h" +#include "../AnimationRender/FrameCallback.h" +#include "../FrameRender/P_Circle.h" +#include "../FrameRender/P_LineSegment.h" +#include "../FrameRender/P_Square.h" +#include "../FrameRender/P_TransformCenter.h" +#include "../FrameRender/PixelCallback.h" +#include + +int +main() { + u32 width = 512; + u32 height = 512; + const u32 FPS = 60; + u32 frames = FPS * 5; + + PixelCallback* child; + TransformCenter childLeft = { .centerX = width / 4, .centerY = height * 3 / 4, }; + TransformCenter childRight = { .centerX = width * 3 / 4, .centerY = height * 3 / 4, }; + + PixelCallback* segment; + LineSegment segmentRight = { + .aX = width / 2, .aY = height / 4, + .bX = width * 3 / 4, .bY = height * 3 / 4, + .width = 20, .color = 0xFFFF00FF, + }; + LineSegment segmentLeft = { + .aX = width / 2, .aY = height / 4, + .bX = width / 4, .bY = height * 3 / 4, + .width = 20, .color = 0xFF0088FF, + }; + + PixelCallback* callbacks[] = { + /* Background */ + Square_setup((Square){ + .size = width, .color = 0xFFF0F0F0, + }), + /* Connecting line */ + NULL, + segment = LineSegment_setup(segmentRight), + /* Root node */ + TransformCenter_setup((TransformCenter){ + .centerX = width / 2, .centerY = height / 4, + }), + Circle_setup((Circle){ + .radius = 60, .color = 0xFFFF0000, + }), + /* Child node */ + NULL, + child = TransformCenter_setup(childRight), + Circle_setup((Circle){ + .radius = 60, .color = 0xFF00FF00, + }), + }; + u32 sizeCallbacks = sizeof(callbacks) / sizeof(*callbacks); + + FrameCallback* frameCallbacks[] = { + /* Move right to left */ + FrameRange_setup((FrameRange){ + .startFrame = frames / 3 - FPS, .endFrame = frames / 3, + }), + Interpolate_setup((Interpolate){ + .startValue = &childRight, .endValue = &childLeft, + .value = child->callback_self, + .interpolate = (f_interpolate)Interpolate_TransformCenter, + }), + Interpolate_setup((Interpolate){ + .startValue = &segmentRight, .endValue = &segmentLeft, + .value = segment->callback_self, + .interpolate = (f_interpolate)Interpolate_LineSegment, + }), + /* Move left to right */ + NULL, + FrameRange_setup((FrameRange){ + .startFrame = frames * 2 / 3 - FPS, .endFrame = frames * 2 / 3, + }), + Interpolate_setup((Interpolate){ + .startValue = &childLeft, .endValue = &childRight, + .value = child->callback_self, + .interpolate = (f_interpolate)Interpolate_TransformCenter, + }), + Interpolate_setup((Interpolate){ + .startValue = &segmentLeft, .endValue = &segmentRight, + .value = segment->callback_self, + .interpolate = (f_interpolate)Interpolate_LineSegment, + }), + /* Render */ + NULL, + Draw_setup((Draw){ + .callbacks = (const PixelCallback**)callbacks, .sizeCallbacks = sizeCallbacks, + }), + }; + u32 sizeFrameCallbacks = sizeof(frameCallbacks) / sizeof(*frameCallbacks); + + RenderAnimation(width, height, frames, (const FrameCallback**)frameCallbacks, sizeFrameCallbacks); + + for (u32 i = 0; i < sizeCallbacks; ++i) { + if (callbacks[i] == NULL) continue; + free(callbacks[i]->callback_self); + free(callbacks[i]); + } + for (u32 i = 0; i < sizeFrameCallbacks; ++i) { + if (frameCallbacks[i] == NULL) continue; + free(frameCallbacks[i]->callback_self); + free(frameCallbacks[i]); + } + + return 0; +} -- cgit v1.2.3