From d31239eeeac4ea595b1d1e7063ab5d762809fb02 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Sat, 28 Mar 2026 20:33:03 +0200 Subject: feat!: Complete rewrite This new scheme will be much simpler --- Animation.c | 118 ------------------------- Animation.h | 44 ---------- AnimationInterpolate.c | 78 ----------------- AnimationInterpolate.h | 22 ----- AnimationMove.c | 34 ------- AnimationMove.h | 31 ------- AnimationObject.c | 78 ----------------- AnimationObject.h | 56 ------------ FrameRender/FrameRender.c | 25 ++++++ FrameRender/FrameRender.h | 10 +++ FrameRender/P_Square.c | 22 +++++ FrameRender/P_Square.h | 14 +++ FrameRender/P_TransformCenter.c | 19 ++++ FrameRender/P_TransformCenter.h | 14 +++ FrameRender/PixelCallback.h | 20 +++++ global.h | 2 +- graphics.c | 190 +++++++--------------------------------- 17 files changed, 155 insertions(+), 622 deletions(-) delete mode 100644 Animation.c delete mode 100644 Animation.h delete mode 100644 AnimationInterpolate.c delete mode 100644 AnimationInterpolate.h delete mode 100644 AnimationMove.c delete mode 100644 AnimationMove.h delete mode 100644 AnimationObject.c delete mode 100644 AnimationObject.h create mode 100644 FrameRender/FrameRender.c create mode 100644 FrameRender/FrameRender.h create mode 100644 FrameRender/P_Square.c create mode 100644 FrameRender/P_Square.h create mode 100644 FrameRender/P_TransformCenter.c create mode 100644 FrameRender/P_TransformCenter.h create mode 100644 FrameRender/PixelCallback.h diff --git a/Animation.c b/Animation.c deleted file mode 100644 index 2dc6380..0000000 --- a/Animation.c +++ /dev/null @@ -1,118 +0,0 @@ -#include "Animation.h" -#include - -struct AnimationEventNode { - AnimationEventNode* next; - - u32 startFrame; - u32 endFrame; - PixelRenderer renderCallback; - void* privateData; -}; - -AnimationEventNode* -AnimationEventNode_new(u32 startFrame, u32 endFrame, PixelRenderer renderCallback, void* privateData) { - AnimationEventNode* aen = (AnimationEventNode*)malloc(sizeof(AnimationEventNode)); - aen->next = NULL; - aen->startFrame = startFrame; - aen->endFrame = endFrame; - aen->renderCallback = renderCallback; - aen->privateData = privateData; - - return aen; -} - -Animation -Animation_new(u32 width, u32 height, u32 frameCount) { - return (Animation){ - .width = width, - .height = height, - .frameCount = frameCount, - .duplicateFrames = 0, - .frameBuffer = RGBImage_new(width, height), - .events = NULL, - }; -} - -void -Animation_free(Animation anim) { - RGBImage_free(anim.frameBuffer); - while (anim.events != NULL) { - AnimationEventNode* toFree = anim.events; - anim.events = anim.events->next; - free(toFree); - } -} - -void -Animation_delete(Animation* anim) { - Animation_free(*anim); - anim->width = anim->height = anim->frameCount = 0; - RGBImage_delete(&anim->frameBuffer); -} - -void -Animation_pushEvent(Animation* anim, u32 startFrame, u32 endFrame, PixelRenderer renderer, void* privateData) { - if (anim->events == NULL) { - anim->events = AnimationEventNode_new(startFrame, endFrame, renderer, privateData); - return; - } - - AnimationEventNode* prevNode = NULL, *currNode = anim->events; - while (currNode != NULL) { - if (startFrame < currNode->startFrame) { - prevNode->next = AnimationEventNode_new(startFrame, endFrame, renderer, privateData); - prevNode->next->next = currNode; - return; - } - - prevNode = currNode; - currNode = currNode->next; - } - - prevNode->next = AnimationEventNode_new(startFrame, endFrame, renderer, privateData); -} - -void -Animation_render(Animation* anim) { - for (u32 currFrame = 0; currFrame < anim->frameCount; ++currFrame) { - if (anim->events != NULL) - for (i32 r = 0; r < anim->frameBuffer.width; ++r) - for (i32 c = 0; c < anim->frameBuffer.height; ++c) { - for (AnimationEventNode* aen = anim->events; aen != NULL && aen->startFrame <= currFrame; aen = aen->next) { - ARGB* pixel = RGBImage_at(anim->frameBuffer, r, c); - ARGB newPixel = aen->renderCallback(anim, (PixelRendererParams){ - .frame = { - .current = currFrame, - .start = aen->startFrame, - .end = aen->endFrame, - }, - .pixel = *pixel, - .row = r, .col = c, - .priv = aen->privateData, - }); - ARGB_merge(pixel, newPixel); - } - - AnimationEventNode* prevNode = NULL, *currNode = anim->events; - while (currNode != NULL && currNode->startFrame <= currFrame) { - if (currNode->endFrame <= currFrame) { - if (prevNode != NULL) - prevNode->next = currNode->next; - else - anim->events = NULL; - free(currNode); - } - else { - prevNode = currNode; - currNode = currNode->next; - } - } - } - - ppm6_write(stdout, anim->frameBuffer); - - for (u32 duplicates = 0; duplicates < anim->duplicateFrames; ++duplicates) - ppm6_write(stdout, anim->frameBuffer); - } -} diff --git a/Animation.h b/Animation.h deleted file mode 100644 index 6cebdb0..0000000 --- a/Animation.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _ANIMATION -#define _ANIMATION - -#include "RGBImage.h" - -struct AnimationEventNode; -typedef struct AnimationEventNode AnimationEventNode; - -typedef struct Animation { - u32 width; - u32 height; - u32 frameCount; - u32 duplicateFrames; - - RGBImage frameBuffer; - AnimationEventNode* events; -} Animation; - -typedef struct PixelRendererParams { - struct Frames { - u32 current; - u32 start; - u32 end; - } frame; - - ARGB pixel; - - i32 row; - i32 col; - - void* priv; -} PixelRendererParams; - -typedef ARGB (*PixelRenderer)(const Animation* anim, PixelRendererParams params); - -AnimationEventNode* AnimationEventNode_new(u32 startFrame, u32 endFrame, PixelRenderer renderCallback, void* privateData); -Animation Animation_new(u32 width, u32 height, u32 frameCount); -void Animation_free(Animation anim); -void Animation_delete(Animation* anim); - -void Animation_pushEvent(Animation* anim, u32 startFrame, u32 endFrame, PixelRenderer renderer, void* privateData); -void Animation_render(Animation* anim); - -#endif /* _ANIMATION */ diff --git a/AnimationInterpolate.c b/AnimationInterpolate.c deleted file mode 100644 index a84b5a2..0000000 --- a/AnimationInterpolate.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "AnimationInterpolate.h" -#include "AnimationObject.h" -#include "AnimationMove.h" -#include - -#define NUM_INTERPOLATE(a, b, perc) (a * (1.0 - (perc)) + b * (perc)) - -color -colorInterpolate(color ina, color inb, double percentage) { - ARGB a, b; - ARGB_set(&a, ina); - ARGB_set(&b, inb); - - a.a = NUM_INTERPOLATE(a.a, b.a, percentage); - a.r = NUM_INTERPOLATE(a.r, b.r, percentage); - a.g = NUM_INTERPOLATE(a.g, b.g, percentage); - a.b = NUM_INTERPOLATE(a.b, b.b, percentage); - - return a.a << 24 | a.r << 16 | a.g << 8 | a.b; -} - -ARGB -A_Interpolate(const Animation* anim, PixelRendererParams a) { - struct A_Interpolate in = *(struct A_Interpolate*)a.priv; - - if (in.interpolate == NULL) { - fprintf(stderr, "Interpolation function cannot be NULL!\n"); - ARGB_set(&a.pixel, 0xFFFF00FF); - return a.pixel; - } - - if (a.frame.current == a.frame.start) { - memcpy(in.initialValueTemp, in.value, in.initialValueTempSize); - } - - double perc = (double)(a.frame.current - a.frame.start) / (a.frame.end - a.frame.start); - if (perc < 0.0) perc = 0.0; - if (perc > 1.0) perc = 1.0; - - in.interpolate(in.value, in.initialValueTemp, in.goalValue, perc); - - return a.pixel; -} - -void -AO_LineInterpolate(void* valueLine, const void* initialLine, const void* finalLine, double percentage) { - struct AO_Line* value = valueLine; - const struct AO_Line* initial = initialLine, *final = finalLine; - - value->a = NUM_INTERPOLATE(initial->a, final->a, percentage); - value->b = NUM_INTERPOLATE(initial->b, final->b, percentage); - value->c = NUM_INTERPOLATE(initial->c, final->c, percentage); - value->width = NUM_INTERPOLATE(initial->width, final->width, percentage); - value->color = colorInterpolate(initial->color, final->color, percentage); -} - -void -AM_LinearInterpolate(void* valueIn, const void* initialIn, const void* finalIn, double percentage) { - struct AM_Linear* value = valueIn; - const struct AM_Linear* initial = initialIn, *final = finalIn; - - value->startRow = NUM_INTERPOLATE(initial->startRow, final->startRow, percentage); - value->startCol = NUM_INTERPOLATE(initial->startCol, final->startCol, percentage); - value->dRow = NUM_INTERPOLATE(initial->dRow, final->dRow, percentage); - value->dCol = NUM_INTERPOLATE(initial->dCol, final->dCol, percentage); - value->wrapCoordinates = NUM_INTERPOLATE(initial->wrapCoordinates, final->wrapCoordinates, percentage); -} - -void -AM_SpinInterpolate(void* valueIn, const void* initialIn, const void* finalIn, double percentage) { - struct AM_Spin* value = valueIn; - const struct AM_Spin* initial = initialIn, *final = finalIn; - - value->theta = NUM_INTERPOLATE(initial->theta, final->theta, percentage); - value->dTheta = NUM_INTERPOLATE(initial->dTheta, final->dTheta, percentage); - value->centerRow = NUM_INTERPOLATE(initial->centerRow, final->centerRow, percentage); - value->centerCol = NUM_INTERPOLATE(initial->centerCol, final->centerCol, percentage); -} diff --git a/AnimationInterpolate.h b/AnimationInterpolate.h deleted file mode 100644 index 18ae841..0000000 --- a/AnimationInterpolate.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _ANIMATION_INTERPOLATE -#define _ANIMATION_INTERPOLATE - -#include "Animation.h" - -struct A_Interpolate { - void* initialValueTemp; - size_t initialValueTempSize; - - void* value; - void* goalValue; - void (*interpolate)(void* value, const void* initialState, const void* finalState, double percentage); -}; - -ARGB A_Interpolate(const Animation* anim, PixelRendererParams params); - -void AO_LineInterpolate(void* valueLine, const void* initialLine, const void* finalLine, double percentage); - -void AM_LinearInterpolate(void* valueLinear, const void* initialLinear, const void* finalLinear, double percentage); -void AM_SpinInterpolate(void* valueSpin, const void* initialSpin, const void* finalSpin, double percentage); - -#endif /* _ANIMATION_INTERPOLATE */ diff --git a/AnimationMove.c b/AnimationMove.c deleted file mode 100644 index 7ac52f9..0000000 --- a/AnimationMove.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "AnimationMove.h" -#include - -ARGB -AM_Linear(const Animation* anim, PixelRendererParams a) { - struct AM_Linear ml = *(struct AM_Linear*)a.priv; - - a.row = (a.row - ml.startRow - (i32)(a.frame.current * ml.dRow)); - a.col = (a.col - ml.startCol - (i32)(a.frame.current * ml.dCol)); - - if (ml.wrapCoordinates == true) { - a.row %= anim->width; - a.col %= anim->height; - } - - a.priv = ml.priv; - return ml.callback(anim, a); -} - -ARGB -AM_Spin(const Animation* anim, PixelRendererParams a) { - struct AM_Spin ms = *(struct AM_Spin*)a.priv; - - double radius = sqrt(a.row * a.row + a.col * a.col); - double phi = atan2(a.col, a.row); - - phi += ms.theta + ms.dTheta * a.frame.current; - - a.row = (ms.centerRow + (i32)(radius * cos(phi))); - a.col = (ms.centerCol + (i32)(radius * sin(phi))); - - a.priv = ms.priv; - return ms.callback(anim, a); -} diff --git a/AnimationMove.h b/AnimationMove.h deleted file mode 100644 index 48a3b92..0000000 --- a/AnimationMove.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _ANIMATION_MOVE -#define _ANIMATION_MOVE - -#include "Animation.h" - -struct AM_Linear { - PixelRenderer callback; - void* priv; - - i32 startRow; - i32 startCol; - float dRow; - float dCol; - bool wrapCoordinates; -}; - -ARGB AM_Linear(const Animation* anim, PixelRendererParams params); - -struct AM_Spin { - PixelRenderer callback; - void* priv; - - float theta; - float dTheta; - i32 centerRow; - i32 centerCol; -}; - -ARGB AM_Spin(const Animation* anim, PixelRendererParams params); - -#endif /* _ANIMATION_MOVE */ diff --git a/AnimationObject.c b/AnimationObject.c deleted file mode 100644 index 63594ce..0000000 --- a/AnimationObject.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "AnimationObject.h" -#include -#include - -ARGB -AO_CheckerPattern(const Animation* anim, PixelRendererParams a) { - struct AO_CheckerPattern chp = *(struct AO_CheckerPattern*)a.priv; - - a.row /= chp.squareSize; - a.col /= chp.squareSize; - - if ((a.row + a.col) % 2 == 0) { - ARGB_set(&a.pixel, 0xFF000000); - } - else { - ARGB_set(&a.pixel, 0xFFFF00FF); - } - - return a.pixel; -} - -ARGB -AO_Square(const Animation* anim, PixelRendererParams a) { - struct AO_Square* set = (struct AO_Square*)a.priv; - - if (0 <= a.row && a.row <= set->width && 0 <= a.col && a.col <= set->height) { - ARGB_set(&a.pixel, set->color); - } - - return a.pixel; -} - -ARGB -AO_Circle(const Animation* anim, PixelRendererParams a) { - struct AO_Circle* cir = (struct AO_Circle*)a.priv; - - if (a.row * a.row + a.col * a.col < cir->radius * cir->radius) { - ARGB_set(&a.pixel, cir->color); - } - - return a.pixel; -} - -ARGB -AO_Image(const Animation* anim, PixelRendererParams a) { - struct AO_Image img = *(struct AO_Image*)a.priv; - - if (img.noRepeat == true && - (a.col < 0 || img.img.width * img.zoom <= a.col || - a.row < 0 || img.img.height * img.zoom <= a.row)) - { - return a.pixel; - } - - return *RGBImage_at(*(RGBImage*)a.priv, a.row / img.zoom, a.col / img.zoom); -} - -ARGB -AO_Line(const Animation* anim, PixelRendererParams a) { - struct AO_Line l = *(struct AO_Line*)a.priv; - - if (fabs(l.a * a.col + l.b * a.row + l.c) / sqrt(l.a * l.a + l.b * l.b) < l.width) { - ARGB_set(&a.pixel, l.color); - } - - return a.pixel; -} - -ARGB -AO_HorSegment(const Animation* anim, PixelRendererParams a) { - struct AO_HorSegment hs = *(struct AO_HorSegment*)a.priv; - - if (abs(a.row) <= hs.width && hs.left <= a.col && a.col <= hs.right) { - ARGB_set(&a.pixel, hs.color); - } - - return a.pixel; -} diff --git a/AnimationObject.h b/AnimationObject.h deleted file mode 100644 index ef8c3a3..0000000 --- a/AnimationObject.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _ANIMATION_OBJECT -#define _ANIMATION_OBJECT - -#include "Animation.h" - -struct AO_CheckerPattern { - u32 squareSize; - color colorA; - color colorB; -}; - -ARGB AO_CheckerPattern(const Animation* anim, PixelRendererParams params); - -struct AO_Square { - u32 width; - u32 height; - color color; -}; - -ARGB AO_Square(const Animation* anim, PixelRendererParams params); - -struct AO_Circle { - double radius; - color color; -}; - -ARGB AO_Circle(const Animation* anim, PixelRendererParams params); - -struct AO_Image { - RGBImage img; - double zoom; - bool noRepeat; -}; - -ARGB AO_Image(const Animation* anim, PixelRendererParams params); - -struct AO_Line { - double a; - double b; - double c; - double width; - color color; -}; - -ARGB AO_Line(const Animation* anim, PixelRendererParams params); - -struct AO_HorSegment { - i32 left; - i32 right; - double width; - color color; -}; - -ARGB AO_HorSegment(const Animation* anim, PixelRendererParams params); - -#endif /* _ANIMATION_OBJECT */ diff --git a/FrameRender/FrameRender.c b/FrameRender/FrameRender.c new file mode 100644 index 0000000..bf148bd --- /dev/null +++ b/FrameRender/FrameRender.c @@ -0,0 +1,25 @@ +#include "FrameRender.h" +#include + +void RenderFrame(RGBImage buffer, const PixelCallback** callbacks, usize sizeCallbacks) { + struct PixelContext pc; + for (u32 x = 0; x < buffer.width; ++x) { + for (u32 y = 0; y < buffer.height; ++y) { + pc.x = x; + pc.y = y; + pc.pixel.a = pc.pixel.r = pc.pixel.g = pc.pixel.b = 0; + + for (usize i = 0; i < sizeCallbacks; ++i) { + // Soft context reset + if (callbacks[i] == NULL) { + pc.x = x; + pc.y = y; + } + else + callbacks[i]->callback(callbacks[i]->callback_self, &pc); + } + + memcpy(RGBImage_at(buffer, y, x), &pc.pixel, sizeof(pc.pixel)); + } + } +} diff --git a/FrameRender/FrameRender.h b/FrameRender/FrameRender.h new file mode 100644 index 0000000..09037cb --- /dev/null +++ b/FrameRender/FrameRender.h @@ -0,0 +1,10 @@ +#ifndef _FRAME_RENDER +#define _FRAME_RENDER + +#include "../global.h" +#include "../RGBImage.h" +#include "PixelCallback.h" + +void RenderFrame(RGBImage buffer, const PixelCallback** callbacks, usize sizeCallbacks); + +#endif /* _FRAME_RENDER */ diff --git a/FrameRender/P_Square.c b/FrameRender/P_Square.c new file mode 100644 index 0000000..7865370 --- /dev/null +++ b/FrameRender/P_Square.c @@ -0,0 +1,22 @@ +#include "P_Square.h" +#include "PixelCallback.h" +#include +#include + +void Square_callback(Square* self, struct PixelContext* fc) { + if (0 <= fc->x && fc->x <= self->width && + 0 <= fc->y && fc->y <= self->height) + { + ARGB_set(&fc->pixel, self->color); + } +} + +PixelCallback* Square_setup(Square obj) { + PixelCallback* pca = malloc(sizeof(struct PixelCallback)); + + pca->callback = (PixelCallback_callback)Square_callback; + pca->callback_self = malloc(sizeof(obj)); + memcpy(pca->callback_self, &obj, sizeof(obj)); + + return pca; +} diff --git a/FrameRender/P_Square.h b/FrameRender/P_Square.h new file mode 100644 index 0000000..1cfbc45 --- /dev/null +++ b/FrameRender/P_Square.h @@ -0,0 +1,14 @@ +#ifndef P_SQUARE +#define P_SQUARE + +#include "PixelCallback.h" + +typedef struct Square { + u32 width; + u32 height; + color color; +} Square; + +PixelCallback* Square_setup(Square obj); + +#endif /* P_SQUARE */ diff --git a/FrameRender/P_TransformCenter.c b/FrameRender/P_TransformCenter.c new file mode 100644 index 0000000..5388437 --- /dev/null +++ b/FrameRender/P_TransformCenter.c @@ -0,0 +1,19 @@ +#include "P_TransformCenter.h" +#include "PixelCallback.h" +#include +#include + +void TransformCenter_callback(TransformCenter* self, struct PixelContext* pc) { + pc->x -= self->centerX; + pc->y -= self->centerY; +} + +PixelCallback* TransformCenter_setup(TransformCenter obj) { + PixelCallback* pca = malloc(sizeof(struct PixelCallback)); + + pca->callback = (PixelCallback_callback)TransformCenter_callback; + pca->callback_self = malloc(sizeof(obj)); + memcpy(pca->callback_self, &obj, sizeof(obj)); + + return pca; +} diff --git a/FrameRender/P_TransformCenter.h b/FrameRender/P_TransformCenter.h new file mode 100644 index 0000000..ab75c32 --- /dev/null +++ b/FrameRender/P_TransformCenter.h @@ -0,0 +1,14 @@ +#ifndef P_TRANSFORMCENTER +#define P_TRANSFORMCENTER + +#include "PixelCallback.h" +#include "../global.h" + +typedef struct TransformCenter { + i32 centerX; + i32 centerY; +} TransformCenter; + +PixelCallback* TransformCenter_setup(TransformCenter obj); + +#endif /* P_TRANSFORMCENTER */ diff --git a/FrameRender/PixelCallback.h b/FrameRender/PixelCallback.h new file mode 100644 index 0000000..b0aee1f --- /dev/null +++ b/FrameRender/PixelCallback.h @@ -0,0 +1,20 @@ +#ifndef _PIXEL_CALLBACK +#define _PIXEL_CALLBACK + +#include "../global.h" +#include "../RGBImage.h" + +struct PixelContext { + i32 x; + i32 y; + ARGB pixel; +}; + +typedef void (*PixelCallback_callback)(void* self, struct PixelContext* pc); + +typedef struct PixelCallback { + PixelCallback_callback callback; + void* callback_self; +} PixelCallback; + +#endif /* _PIXEL_CALLBACK */ diff --git a/global.h b/global.h index 9b322a9..fc31f28 100644 --- a/global.h +++ b/global.h @@ -9,6 +9,6 @@ typedef uint8_t bool; typedef int32_t i32; typedef uint32_t u32; - +typedef uint32_t usize; #endif /* _GLOBAL */ diff --git a/graphics.c b/graphics.c index 4ac5055..6281f6f 100644 --- a/graphics.c +++ b/graphics.c @@ -2,169 +2,39 @@ * gcc -std=c99 *.c -lm && ./a.out | ffmpeg -r 30 -i - output.mp4 */ -#include "Animation.h" -#include "AnimationObject.h" -#include "AnimationMove.h" -#include "AnimationInterpolate.h" -#include - -double -pointDistance(i32 rowA, i32 colA, i32 rowB, i32 colB) { - return sqrt(pow(rowA - rowB, 2) + pow(colA - colB, 2)); -} - -void -HorSegmentByPoints( - i32 rowA, i32 colA, i32 rowB, i32 colB, - struct AO_HorSegment* segment, - struct AM_Spin* rotate, - struct AM_Linear* translate) -{ - segment->left = 0; - segment->right = pointDistance(rowA, colA, rowB, colB); - - rotate->theta = atan2(rowB - rowA, colB - colA); - - translate->startRow = rowA; - translate->startCol = colA; - - rotate->callback = AO_HorSegment; - rotate->priv = segment; - translate->callback = AM_Spin; - translate->priv = rotate; -} +#include "FrameRender/FrameRender.h" +#include "FrameRender/P_Square.h" +#include "FrameRender/P_TransformCenter.h" +#include "RGBImage.h" +#include int main() { - const u32 FPS = 60; - Animation anim = Animation_new(512, 512, FPS * 5); - - struct AO_Square background = { - .width = anim.width, .height = anim.height, - .color = 0xFFF0F0F0, - }; - Animation_pushEvent(&anim, 0, anim.frameCount, AO_Square, &background); - - /* Root node */ - struct AO_Circle rootNode_ = { - .radius = 60, .color = 0xFFFF0000, - }; - struct AM_Linear rootNode_linear = { - .callback = AO_Circle, .priv = &rootNode_, - - .startRow = anim.height / 4, .startCol = anim.width / 2, - }; - - struct AM_Linear rootNode = rootNode_linear; - - /* Child node */ - struct AO_Circle childNode_ = { - .radius = 60, .color = 0xFF00FF00, - }; - - struct AM_Linear childNode_left = { - .callback = AO_Circle, .priv = &childNode_, - - .startRow = anim.height * 3 / 4, .startCol = anim.width / 4, - }; - struct AM_Linear childNode_right = { - .callback = AO_Circle, .priv = &childNode_, - - .startRow = anim.height * 3 / 4, .startCol = anim.width * 3 / 4, - }; - - struct AM_Linear childNode = childNode_right; - - /* Root Node --- Child Node */ - struct AO_HorSegment link_ = { - .color = 0xFFFF00FF, .width = 10, - }; - - struct AM_Spin link_spin_left = {}; - struct AM_Linear link_translate_left = {}; - HorSegmentByPoints( - rootNode_linear.startRow, rootNode_linear.startCol, - childNode_left.startRow, childNode_left.startCol, - &link_, &link_spin_left, &link_translate_left); - - struct AM_Spin link_spin_right = {}; - struct AM_Linear link_translate_right = {}; - HorSegmentByPoints( - rootNode_linear.startRow, rootNode_linear.startCol, - childNode_right.startRow, childNode_right.startCol, - &link_, &link_spin_right, &link_translate_right); - - struct AM_Spin link_spin = link_spin_right; - struct AM_Linear link_translate = link_translate_right; - link_translate.priv = &link_spin; - - Animation_pushEvent(&anim, 0, anim.frameCount, AM_Linear, &link_translate); - Animation_pushEvent(&anim, 0, anim.frameCount, AM_Linear, &rootNode); - Animation_pushEvent(&anim, 0, anim.frameCount, AM_Linear, &childNode); - - /* Movement */ - - struct AM_Linear temp1; - struct A_Interpolate childNode_moveToLeft = { - .initialValueTemp = &temp1, .initialValueTempSize = sizeof(temp1), - - .interpolate = AM_LinearInterpolate, - .value = &childNode, .goalValue = &childNode_left, - }; - struct AM_Spin temp11; - struct A_Interpolate segment_spin_moveToLeft = { - .initialValueTemp = &temp11, .initialValueTempSize = sizeof(temp11), - - .interpolate = AM_SpinInterpolate, - .value = &link_spin, .goalValue = &link_spin_left, - }; - struct AM_Linear temp12; - struct A_Interpolate segment_translate_moveToLeft = { - .initialValueTemp = &temp12, .initialValueTempSize = sizeof(temp12), - - .interpolate = AM_LinearInterpolate, - .value = &link_translate, .goalValue = &link_translate_left, - }; - - struct AM_Linear temp2; - struct A_Interpolate childNode_moveToRight = { - .initialValueTemp = &temp2, .initialValueTempSize = sizeof(temp2), - - .interpolate = AM_LinearInterpolate, - .value = &childNode, .goalValue = &childNode_right, - }; - struct AM_Spin temp21; - struct A_Interpolate segment_spin_moveToRight = { - .initialValueTemp = &temp21, .initialValueTempSize = sizeof(temp21), - - .interpolate = AM_SpinInterpolate, - .value = &link_spin, .goalValue = &link_spin_right, - }; - struct AM_Linear temp22; - struct A_Interpolate segment_translate_moveToRight = { - .initialValueTemp = &temp22, .initialValueTempSize = sizeof(temp22), - - .interpolate = AM_LinearInterpolate, - .value = &link_translate, .goalValue = &link_translate_right, - }; - - /* Move child node from right to left */ - - u32 start = anim.frameCount / 3 - FPS, end = anim.frameCount / 3; - Animation_pushEvent(&anim, start, end, A_Interpolate, &childNode_moveToLeft); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_spin_moveToLeft); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_translate_moveToLeft); - - /* Move child node from left to right */ - - start = anim.frameCount * 2 / 3 - FPS, end = anim.frameCount * 2 / 3; - Animation_pushEvent(&anim, start, end, A_Interpolate, &childNode_moveToRight); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_spin_moveToRight); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_translate_moveToRight); - - Animation_render(&anim); - - Animation_delete(&anim); + RGBImage frame = RGBImage_new(512, 512); + + PixelCallback* callbacks[] = { + TransformCenter_setup((TransformCenter){ + .centerX = frame.width / 2, .centerY = frame.width / 2, + }), + Square_setup((Square){ + .width = 100, .height = 100, .color = 0xFFFF0000, + }), + NULL, + Square_setup((Square){ + .width = 200, .height = 200, .color = 0xFF00FFFF, + }), + }; + u32 sizeCallbacks = sizeof(callbacks) / sizeof(*callbacks); + + RenderFrame(frame, (const PixelCallback**)callbacks, sizeCallbacks); + ppm6_write(stdout, frame); + + RGBImage_delete(&frame); + for (u32 i = 0; i < sizeCallbacks; ++i) { + if (callbacks[i] == NULL) continue; + free(callbacks[i]->callback_self); + free(callbacks[i]); + } return 0; } -- cgit v1.2.3